Merge "Use default visibility for Snapshot::getLocalClip (attempt #2)."
diff --git a/Android.mk b/Android.mk
index 89b2884..9828ea6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -147,6 +147,8 @@
 	core/java/android/hardware/display/IDisplayManagerCallback.aidl \
 	core/java/android/hardware/hdmi/IHdmiCecListener.aidl \
 	core/java/android/hardware/hdmi/IHdmiCecService.aidl \
+	core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \
+	core/java/android/hardware/hdmi/IHdmiControlService.aidl \
 	core/java/android/hardware/input/IInputManager.aidl \
 	core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
 	core/java/android/hardware/location/IFusedLocationHardware.aidl \
@@ -324,7 +326,6 @@
 	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
-	telephony/java/com/android/internal/telephony/ITelephonyListener.aidl \
 	telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl \
 	telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl \
 	telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl \
@@ -333,7 +334,7 @@
 	telephony/java/com/android/internal/telephony/ISms.aidl \
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
-	wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl \
+	wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl \
 	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
 	wifi/java/android/net/wifi/IWifiScanner.aidl \
 	packages/services/PacProcessor/com/android/net/IProxyService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 68e7c71..fd28b52 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6630,6 +6630,7 @@
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
     field public static final java.lang.String HDMI_CEC_SERVICE = "hdmi_cec";
+    field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
     field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
@@ -6660,8 +6661,8 @@
     field public static final java.lang.String USER_SERVICE = "user";
     field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
     field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
-    field public static final java.lang.String WIFI_HOTSPOT_SERVICE = "wifihotspot";
     field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
+    field public static final java.lang.String WIFI_PASSPOINT_SERVICE = "wifipasspoint";
     field public static final java.lang.String WIFI_SERVICE = "wifi";
     field public static final java.lang.String WINDOW_SERVICE = "window";
   }
@@ -12503,9 +12504,15 @@
     field public static final int MESSAGE_VENDOR_REMOTE_BUTTON_UP = 139; // 0x8b
     field public static final int POWER_STATUS_ON = 0; // 0x0
     field public static final int POWER_STATUS_STANDBY = 1; // 0x1
+    field public static final int POWER_STATUS_TRANSIENT_TO_ON = 2; // 0x2
+    field public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3; // 0x3
     field public static final int POWER_STATUS_UNKNOWN = -1; // 0xffffffff
-    field public static final int POWER_TRANSIENT_TO_ON = 2; // 0x2
-    field public static final int POWER_TRANSIENT_TO_STANDBY = 3; // 0x3
+    field public static final int RESULT_ALREADY_IN_PROGRESS = 4; // 0x4
+    field public static final int RESULT_EXCEPTION = 5; // 0x5
+    field public static final int RESULT_SOURCE_NOT_AVAILABLE = 2; // 0x2
+    field public static final int RESULT_SUCCESS = 0; // 0x0
+    field public static final int RESULT_TARGET_NOT_AVAILABLE = 3; // 0x3
+    field public static final int RESULT_TIMEOUT = 1; // 0x1
     field public static final int UNKNOWN_VENDOR_ID = 16777215; // 0xffffff
   }
 
@@ -12551,6 +12558,27 @@
     field public static final byte[] EMPTY_PARAM;
   }
 
+  public final class HdmiControlManager {
+    method public android.hardware.hdmi.HdmiPlaybackClient getPlaybackClient();
+    method public android.hardware.hdmi.HdmiTvClient getTvClient();
+  }
+
+  public final class HdmiPlaybackClient {
+    method public void oneTouchPlay(android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback);
+    method public void queryDisplayStatus(android.hardware.hdmi.HdmiPlaybackClient.DisplayStatusCallback);
+  }
+
+  public static abstract interface HdmiPlaybackClient.DisplayStatusCallback {
+    method public abstract void onComplete(int);
+  }
+
+  public static abstract interface HdmiPlaybackClient.OneTouchPlayCallback {
+    method public abstract void onComplete(int);
+  }
+
+  public final class HdmiTvClient {
+  }
+
 }
 
 package android.hardware.input {
@@ -13707,16 +13735,17 @@
     ctor public DeniedByServerException(java.lang.String);
   }
 
-  public final class DngCreator {
+  public final class DngCreator implements java.lang.AutoCloseable {
     ctor public DngCreator(android.hardware.camera2.CameraCharacteristics, android.hardware.camera2.CaptureResult);
+    method public void close();
     method public android.media.DngCreator setDescription(java.lang.String);
     method public android.media.DngCreator setLocation(android.location.Location);
     method public android.media.DngCreator setOrientation(int);
     method public android.media.DngCreator setThumbnail(android.graphics.Bitmap);
     method public android.media.DngCreator setThumbnail(android.media.Image);
-    method public void writeByteBuffer(java.io.OutputStream, java.nio.ByteBuffer, int, long) throws java.io.IOException;
+    method public void writeByteBuffer(java.io.OutputStream, android.util.Size, java.nio.ByteBuffer, long) throws java.io.IOException;
     method public void writeImage(java.io.OutputStream, android.media.Image) throws java.io.IOException;
-    method public void writeInputStream(java.io.OutputStream, java.io.InputStream, int, long) throws java.io.IOException;
+    method public void writeInputStream(java.io.OutputStream, android.util.Size, java.io.InputStream, long) throws java.io.IOException;
   }
 
   public class ExifInterface {
@@ -15846,6 +15875,48 @@
     field public int serverAddress;
   }
 
+  public class LinkAddress implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.net.InetAddress getAddress();
+    method public int getFlags();
+    method public int getNetworkPrefixLength();
+    method public int getScope();
+    method public boolean isSameAddressAs(android.net.LinkAddress);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class LinkProperties implements android.os.Parcelable {
+    ctor public LinkProperties();
+    ctor public LinkProperties(android.net.LinkProperties);
+    method public void addDns(java.net.InetAddress);
+    method public boolean addLinkAddress(android.net.LinkAddress);
+    method public void addRoute(android.net.RouteInfo);
+    method public void clear();
+    method public int describeContents();
+    method public java.util.Collection<java.lang.String> getAllInterfaceNames();
+    method public java.util.Collection<java.net.InetAddress> getDnses();
+    method public java.lang.String getDomains();
+    method public android.net.ProxyInfo getHttpProxy();
+    method public java.lang.String getInterfaceName();
+    method public java.util.Collection<android.net.LinkAddress> getLinkAddresses();
+    method public java.util.Collection<android.net.RouteInfo> getRoutes();
+    method public boolean hasIPv4Address();
+    method public boolean hasIPv6Address();
+    method public boolean removeLinkAddress(android.net.LinkAddress);
+    method public void setDomains(java.lang.String);
+    method public void setHttpProxy(android.net.ProxyInfo);
+    method public void setInterfaceName(java.lang.String);
+    method public void setLinkAddresses(java.util.Collection<android.net.LinkAddress>);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static class LinkProperties.CompareResult {
+    ctor public LinkProperties.CompareResult();
+    field public java.util.Collection added;
+    field public java.util.Collection removed;
+  }
+
   public class LocalServerSocket {
     ctor public LocalServerSocket(java.lang.String) throws java.io.IOException;
     ctor public LocalServerSocket(java.io.FileDescriptor) throws java.io.IOException;
@@ -15914,6 +15985,44 @@
     field public static final java.lang.String MAILTO_SCHEME = "mailto:";
   }
 
+  public final class NetworkCapabilities implements android.os.Parcelable {
+    ctor public NetworkCapabilities();
+    ctor public NetworkCapabilities(android.net.NetworkCapabilities);
+    method public void addNetworkCapability(int);
+    method public void addTransportType(int);
+    method public int describeContents();
+    method public int getLinkDownstreamBandwidthKbps();
+    method public int getLinkUpstreamBandwidthKbps();
+    method public java.util.Collection<java.lang.Integer> getNetworkCapabilities();
+    method public java.util.Collection<java.lang.Integer> getTransportTypes();
+    method public boolean hasCapability(int);
+    method public boolean hasTransport(int);
+    method public void removeNetworkCapability(int);
+    method public void removeTransportType(int);
+    method public void setLinkDownstreamBandwidthKbps(int);
+    method public void setLinkUpstreamBandwidthKbps(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int NET_CAPABILITY_CBS = 5; // 0x5
+    field public static final int NET_CAPABILITY_DUN = 2; // 0x2
+    field public static final int NET_CAPABILITY_EIMS = 10; // 0xa
+    field public static final int NET_CAPABILITY_FOTA = 3; // 0x3
+    field public static final int NET_CAPABILITY_IA = 7; // 0x7
+    field public static final int NET_CAPABILITY_IMS = 4; // 0x4
+    field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc
+    field public static final int NET_CAPABILITY_MMS = 0; // 0x0
+    field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
+    field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
+    field public static final int NET_CAPABILITY_RCS = 8; // 0x8
+    field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
+    field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6
+    field public static final int NET_CAPABILITY_XCAP = 9; // 0x9
+    field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2
+    field public static final int TRANSPORT_CELLULAR = 0; // 0x0
+    field public static final int TRANSPORT_ETHERNET = 3; // 0x3
+    field public static final int TRANSPORT_WIFI = 1; // 0x1
+  }
+
   public class NetworkInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.net.NetworkInfo.DetailedState getDetailedState();
@@ -15987,6 +16096,20 @@
     method public void writeToParcel(android.os.Parcel, int);
   }
 
+  public class RouteInfo implements android.os.Parcelable {
+    ctor public RouteInfo(android.net.LinkAddress, java.net.InetAddress, java.lang.String);
+    ctor public RouteInfo(android.net.LinkAddress, java.net.InetAddress);
+    ctor public RouteInfo(java.net.InetAddress);
+    ctor public RouteInfo(android.net.LinkAddress);
+    method public int describeContents();
+    method public android.net.LinkAddress getDestination();
+    method public java.net.InetAddress getGateway();
+    method public java.lang.String getInterface();
+    method public boolean isDefaultRoute();
+    method public boolean matches(java.net.InetAddress);
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     ctor public deprecated SSLCertificateSocketFactory(int);
     method public java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException;
@@ -16823,6 +16946,86 @@
     method public void setWorkSource(android.os.WorkSource);
   }
 
+  public class WifiScanner {
+    method public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.HotspotInfo[]);
+    method public void resetHotlist(android.net.wifi.WifiScanner.HotlistListener);
+    method public void retrieveScanResults(boolean, android.net.wifi.WifiScanner.ScanListener);
+    method public void setHotlist(android.net.wifi.WifiScanner.HotspotInfo[], int, android.net.wifi.WifiScanner.HotlistListener);
+    method public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
+    method public void startTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
+    method public void stopBackgroundScan(android.net.wifi.WifiScanner.ScanListener);
+    method public void stopTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
+    field public static final int MAX_SCAN_PERIOD_MS = 1024000; // 0xfa000
+    field public static final int MIN_SCAN_PERIOD_MS = 2000; // 0x7d0
+    field public static final int REASON_CONFLICTING_REQUEST = -4; // 0xfffffffc
+    field public static final int REASON_INVALID_LISTENER = -2; // 0xfffffffe
+    field public static final int REASON_INVALID_REQUEST = -3; // 0xfffffffd
+    field public static final int REASON_SUCCEEDED = 0; // 0x0
+    field public static final int REASON_UNSPECIFIED = -1; // 0xffffffff
+    field public static final int REPORT_EVENT_AFTER_BUFFER_FULL = 0; // 0x0
+    field public static final int REPORT_EVENT_AFTER_EACH_SCAN = 1; // 0x1
+    field public static final int REPORT_EVENT_FULL_SCAN_RESULT = 2; // 0x2
+    field public static final int WIFI_BAND_24_GHZ = 1; // 0x1
+    field public static final int WIFI_BAND_5_GHZ = 2; // 0x2
+    field public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 4; // 0x4
+    field public static final int WIFI_BAND_5_GHZ_WITH_DFS = 6; // 0x6
+    field public static final int WIFI_BAND_BOTH = 3; // 0x3
+    field public static final int WIFI_BAND_BOTH_WITH_DFS = 7; // 0x7
+    field public static final int WIFI_BAND_UNSPECIFIED = 0; // 0x0
+  }
+
+  public static class WifiScanner.ChannelSpec {
+    ctor public WifiScanner.ChannelSpec(int);
+    field public int frequency;
+  }
+
+  public static class WifiScanner.FullScanResult implements android.os.Parcelable {
+    ctor public WifiScanner.FullScanResult();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public android.net.wifi.WifiScanner.InformationElement[] informationElements;
+    field public android.net.wifi.ScanResult result;
+  }
+
+  public static abstract interface WifiScanner.HotlistListener {
+    method public abstract void onFound(android.net.wifi.ScanResult[]);
+  }
+
+  public static class WifiScanner.HotspotInfo {
+    ctor public WifiScanner.HotspotInfo();
+    field public java.lang.String bssid;
+    field public int frequencyHint;
+    field public int high;
+    field public int low;
+  }
+
+  public static class WifiScanner.InformationElement {
+    ctor public WifiScanner.InformationElement();
+    field public byte[] bytes;
+    field public int id;
+  }
+
+  public static abstract interface WifiScanner.ScanListener {
+    method public abstract void onFullResult(android.net.wifi.WifiScanner.FullScanResult);
+    method public abstract void onPeriodChanged(int);
+    method public abstract void onResults(android.net.wifi.ScanResult[]);
+  }
+
+  public static class WifiScanner.ScanSettings implements android.os.Parcelable {
+    ctor public WifiScanner.ScanSettings();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public int band;
+    field public android.net.wifi.WifiScanner.ChannelSpec[] channels;
+    field public int periodInMs;
+    field public int reportEvents;
+  }
+
+  public static abstract interface WifiScanner.WifiChangeListener {
+    method public abstract void onChanging(android.net.wifi.ScanResult[]);
+    method public abstract void onQuiescence(android.net.wifi.ScanResult[]);
+  }
+
   public class WpsInfo implements android.os.Parcelable {
     ctor public WpsInfo();
     ctor public WpsInfo(android.net.wifi.WpsInfo);
@@ -16840,19 +17043,6 @@
 
 }
 
-package android.net.wifi.hotspot {
-
-  public abstract interface IWifiHotspotManager implements android.os.IInterface {
-    method public abstract void test() throws android.os.RemoteException;
-  }
-
-  public class WifiHotspotManager {
-    ctor public WifiHotspotManager(android.content.Context, android.net.wifi.hotspot.IWifiHotspotManager);
-    method public void test();
-  }
-
-}
-
 package android.net.wifi.p2p {
 
   public class WifiP2pConfig implements android.os.Parcelable {
@@ -17048,6 +17238,114 @@
 
 }
 
+package android.net.wifi.passpoint {
+
+  public abstract interface IPasspointManager implements android.os.IInterface {
+    method public abstract android.os.Messenger getMessenger() throws android.os.RemoteException;
+    method public abstract int getPasspointState() throws android.os.RemoteException;
+  }
+
+  public class PasspointCredential implements android.os.Parcelable {
+    ctor public PasspointCredential();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+  public class PasspointInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ANQP_CAPABILITY = 1; // 0x1
+    field public static final int CELLULAR_NETWORK = 64; // 0x40
+    field public static final int CONNECTION_CAPABILITY = 2048; // 0x800
+    field public static final int DOMAIN_NAME = 128; // 0x80
+    field public static final int HOTSPOT_CAPABILITY = 256; // 0x100
+    field public static final int IP_ADDR_TYPE_AVAILABILITY = 16; // 0x10
+    field public static final int NAI_REALM = 32; // 0x20
+    field public static final int NETWORK_AUTH_TYPE = 4; // 0x4
+    field public static final int OPERATOR_FRIENDLY_NAME = 512; // 0x200
+    field public static final int OSU_PROVIDER = 4096; // 0x1000
+    field public static final int PRESET_ALL = 8191; // 0x1fff
+    field public static final int PRESET_CRED_MATCH = 481; // 0x1e1
+    field public static final int ROAMING_CONSORTIUM = 8; // 0x8
+    field public static final int VENUE_NAME = 2; // 0x2
+    field public static final int WAN_METRICS = 1024; // 0x400
+    field public java.lang.String bssid;
+    field public java.lang.String cellularNetwork;
+    field public java.lang.String connectionCapability;
+    field public java.lang.String domainName;
+    field public java.lang.String ipAddrTypeAvaibility;
+    field public java.lang.String naiRealm;
+    field public java.lang.String networkAuthType;
+    field public java.lang.String operatorFriendlyName;
+    field public java.util.List osuProviderList;
+    field public java.lang.String roamingConsortium;
+    field public java.lang.String venueName;
+    field public java.lang.String wanMetrics;
+  }
+
+  public class PasspointManager {
+    ctor public PasspointManager(android.content.Context, android.net.wifi.passpoint.IPasspointManager);
+    method public boolean addCredential(android.net.wifi.passpoint.PasspointCredential);
+    method public void connect(android.net.wifi.passpoint.PasspointPolicy);
+    method public int getPasspointState();
+    method public java.util.List<android.net.wifi.passpoint.PasspointCredential> getSavedCredentials();
+    method public android.net.wifi.passpoint.PasspointManager.Channel initialize(android.content.Context, android.os.Looper, android.net.wifi.passpoint.PasspointManager.ChannelListener);
+    method public boolean removeCredential(android.net.wifi.passpoint.PasspointCredential);
+    method public java.util.List<android.net.wifi.passpoint.PasspointPolicy> requestCredentialMatch(java.util.List<android.net.wifi.ScanResult>);
+    method public void requestOsuIcons(android.net.wifi.passpoint.PasspointManager.Channel, java.util.List<android.net.wifi.passpoint.PasspointOsuProvider>, int, android.net.wifi.passpoint.PasspointManager.ActionListener);
+    method public boolean updateCredential(android.net.wifi.passpoint.PasspointCredential);
+    field public static final int BUSY = 2; // 0x2
+    field public static final int ERROR = 0; // 0x0
+    field public static final java.lang.String PASSPOINT_CRED_CHANGED_ACTION = "android.net.wifi.passpoint.CRED_CHANGE";
+    field public static final int PASSPOINT_STATE_ACCESS = 3; // 0x3
+    field public static final java.lang.String PASSPOINT_STATE_CHANGED_ACTION = "android.net.wifi.passpoint.STATE_CHANGE";
+    field public static final int PASSPOINT_STATE_DISABLED = 1; // 0x1
+    field public static final int PASSPOINT_STATE_DISCOVERY = 2; // 0x2
+    field public static final int PASSPOINT_STATE_PROVISION = 4; // 0x4
+    field public static final int PASSPOINT_STATE_UNKNOWN = 0; // 0x0
+    field public static final int WIFI_DISABLED = 1; // 0x1
+  }
+
+  public static abstract interface PasspointManager.ActionListener {
+    method public abstract void onFailure(int);
+    method public abstract void onSuccess();
+  }
+
+  public static class PasspointManager.Channel {
+  }
+
+  public static abstract interface PasspointManager.ChannelListener {
+    method public abstract void onChannelDisconnected();
+  }
+
+  public class PasspointOsuProvider implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int OSU_METHOD_OMADM = 0; // 0x0
+    field public static final int OSU_METHOD_SOAP = 1; // 0x1
+    field public static final int OSU_METHOD_UNKNOWN = -1; // 0xffffffff
+    field public java.lang.String friendlyName;
+    field public java.lang.Object icon;
+    field public java.lang.String iconFileName;
+    field public int iconHeight;
+    field public java.lang.String iconType;
+    field public int iconWidth;
+    field public int osuMethod;
+    field public java.lang.String osuNai;
+    field public java.lang.String osuService;
+    field public java.lang.String serverUri;
+    field public java.lang.String ssid;
+  }
+
+  public class PasspointPolicy implements android.os.Parcelable {
+    ctor public PasspointPolicy();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
+}
+
 package android.nfc {
 
   public class FormatException extends java.lang.Exception {
@@ -26510,6 +26808,83 @@
     enum_constant public static final android.telecomm.CallState RINGING;
   }
 
+  public abstract class Connection {
+    ctor protected Connection();
+    method public final android.telecomm.CallAudioState getCallAudioState();
+    method public final android.net.Uri getHandle();
+    method protected void onAbort();
+    method protected void onAnswer();
+    method protected void onDisconnect();
+    method protected void onHold();
+    method protected void onPlayDtmfTone(char);
+    method protected void onReject();
+    method protected void onSetAudioState(android.telecomm.CallAudioState);
+    method protected void onSetSignal(android.os.Bundle);
+    method protected void onStopDtmfTone();
+    method protected void onUnhold();
+    method protected void setActive();
+    method public void setAudioState(android.telecomm.CallAudioState);
+    method protected void setDialing();
+    method protected void setDisconnected(int, java.lang.String);
+    method protected void setHandle(android.net.Uri);
+    method protected void setOnHold();
+    method protected void setRinging();
+    method public static java.lang.String stateToString(int);
+  }
+
+  public static abstract interface Connection.Listener {
+    method public abstract void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
+    method public abstract void onDestroyed(android.telecomm.Connection);
+    method public abstract void onDisconnected(android.telecomm.Connection, int, java.lang.String);
+    method public abstract void onHandleChanged(android.telecomm.Connection, android.net.Uri);
+    method public abstract void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
+    method public abstract void onStateChanged(android.telecomm.Connection, int);
+  }
+
+  public static class Connection.ListenerBase implements android.telecomm.Connection.Listener {
+    ctor public Connection.ListenerBase();
+    method public void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
+    method public void onDestroyed(android.telecomm.Connection);
+    method public void onDisconnected(android.telecomm.Connection, int, java.lang.String);
+    method public void onHandleChanged(android.telecomm.Connection, android.net.Uri);
+    method public void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
+    method public void onStateChanged(android.telecomm.Connection, int);
+  }
+
+  public final class Connection.State {
+    field public static final int ACTIVE = 3; // 0x3
+    field public static final int DIALING = 2; // 0x2
+    field public static final int DISCONNECTED = 5; // 0x5
+    field public static final int HOLDING = 4; // 0x4
+    field public static final int NEW = 0; // 0x0
+    field public static final int RINGING = 1; // 0x1
+  }
+
+  public final class ConnectionRequest {
+    ctor public ConnectionRequest(android.net.Uri, android.os.Bundle);
+    method public android.os.Bundle getExtras();
+    method public android.net.Uri getHandle();
+  }
+
+  public abstract class ConnectionService extends android.telecomm.CallService {
+    ctor public ConnectionService();
+    method public final void abort(java.lang.String);
+    method public final void answer(java.lang.String);
+    method public final void call(android.telecomm.CallInfo);
+    method public final void disconnect(java.lang.String);
+    method public final void hold(java.lang.String);
+    method public final void isCompatibleWith(android.telecomm.CallInfo);
+    method public final void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
+    method public void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
+    method public void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
+    method public void onFindSubscriptions(android.net.Uri, android.telecomm.Response<android.net.Uri, android.telecomm.Subscription>);
+    method public final void playDtmfTone(java.lang.String, char);
+    method public final void reject(java.lang.String);
+    method public final void setIncomingCallId(java.lang.String, android.os.Bundle);
+    method public final void stopDtmfTone(java.lang.String);
+    method public final void unhold(java.lang.String);
+  }
+
   public class GatewayInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.net.Uri getGatewayHandle();
@@ -26561,6 +26936,18 @@
     method protected abstract void updateCall(android.telecomm.InCallCall);
   }
 
+  public abstract interface Response {
+    method public abstract void onError(IN, java.lang.String);
+    method public abstract void onResult(IN, OUT...);
+  }
+
+  public class Subscription implements android.os.Parcelable {
+    ctor public Subscription();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public final class TelecommConstants {
     ctor public TelecommConstants();
     field public static final java.lang.String ACTION_CALL_SERVICE;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 71e4e82..5fd288f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3010,19 +3010,10 @@
                 int h;
                 if (w < 0) {
                     Resources res = r.activity.getResources();
-                    Configuration config = res.getConfiguration();
-                    boolean useAlternateRecents = (config.smallestScreenWidthDp < 600);
-                    if (useAlternateRecents) {
-                        int wId = com.android.internal.R.dimen.recents_thumbnail_width;
-                        int hId = com.android.internal.R.dimen.recents_thumbnail_height;
-                        mThumbnailWidth = w = res.getDimensionPixelSize(wId);
-                        mThumbnailHeight = h = res.getDimensionPixelSize(hId);
-                    } else {
-                        mThumbnailHeight = h =
-                            res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
-                        mThumbnailWidth = w =
-                            res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
-                    }
+                    int wId = com.android.internal.R.dimen.recents_thumbnail_width;
+                    int hId = com.android.internal.R.dimen.recents_thumbnail_height;
+                    mThumbnailWidth = w = res.getDimensionPixelSize(wId);
+                    mThumbnailHeight = h = res.getDimensionPixelSize(hId);
                 } else {
                     h = mThumbnailHeight;
                 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index eeb5283..ca6b008 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -81,8 +81,8 @@
 import android.net.nsd.NsdManager;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiManager;
-import android.net.wifi.hotspot.IWifiHotspotManager;
-import android.net.wifi.hotspot.WifiHotspotManager;
+import android.net.wifi.passpoint.IPasspointManager;
+import android.net.wifi.passpoint.PasspointManager;
 import android.net.wifi.p2p.IWifiP2pManager;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcManager;
@@ -578,11 +578,11 @@
                     return new WifiManager(ctx.getOuterContext(), service);
                 }});
 
-        registerService(WIFI_HOTSPOT_SERVICE, new ServiceFetcher() {
+        registerService(WIFI_PASSPOINT_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
-                    IBinder b = ServiceManager.getService(WIFI_HOTSPOT_SERVICE);
-                    IWifiHotspotManager service = IWifiHotspotManager.Stub.asInterface(b);
-                    return new WifiHotspotManager(ctx.getOuterContext(), service);
+                    IBinder b = ServiceManager.getService(WIFI_PASSPOINT_SERVICE);
+                    IPasspointManager service = IPasspointManager.Stub.asInterface(b);
+                    return new PasspointManager(ctx.getOuterContext(), service);
                 }});
 
         registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a364e68..f7f51fe 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1991,7 +1991,7 @@
             //@hide: NETWORK_STATS_SERVICE,
             //@hide: NETWORK_POLICY_SERVICE,
             WIFI_SERVICE,
-            WIFI_HOTSPOT_SERVICE,
+            WIFI_PASSPOINT_SERVICE,
             WIFI_P2P_SERVICE,
             WIFI_SCANNING_SERVICE,
             NSD_SERVICE,
@@ -2352,13 +2352,13 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
-     * android.net.wifi.hotspot.WifiHotspotManager} for handling management of
-     * Wi-Fi hotspot access.
+     * android.net.wifi.passpoint.PasspointManager} for handling management of
+     * Wi-Fi passpoint access.
      *
      * @see #getSystemService
-     * @see android.net.wifi.hotspot.WifiHotspotManager
+     * @see android.net.wifi.passpoint.PasspointManager
      */
-    public static final String WIFI_HOTSPOT_SERVICE = "wifihotspot";
+    public static final String WIFI_PASSPOINT_SERVICE = "wifipasspoint";
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
@@ -2583,13 +2583,24 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
-     * {@link android.hardware.hdmi.HdmiCecManager for controlling and managing
+     * {@link android.hardware.hdmi.HdmiCecManager} for controlling and managing
      * HDMI-CEC protocol.
      *
      * @see #getSystemService
      * @see android.hardware.hdmi.HdmiCecManager
      */
-     public static final String HDMI_CEC_SERVICE = "hdmi_cec";
+    // TODO: Remove this once HdmiControlService is ready.
+    public static final String HDMI_CEC_SERVICE = "hdmi_cec";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.hardware.hdmi.HdmiControlManager} for controlling and managing
+     * HDMI-CEC protocol.
+     *
+     * @see #getSystemService
+     * @see android.hardware.hdmi.HdmiControlManager
+     */
+    public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
 
     /**
      * Use with {@link #getSystemService} to retrieve a
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 1127fe5..7cc6d1d 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -30,6 +30,8 @@
  * through the {@link CameraManager CameraManager}
  * interface in addition to through the CameraDevice interface.</p>
  *
+ * <p>{@link CameraCharacteristics} objects are immutable.</p>
+ *
  * @see CameraDevice
  * @see CameraManager
  */
@@ -47,6 +49,14 @@
         mProperties = properties;
     }
 
+    /**
+     * Returns a copy of the underlying {@link CameraMetadataNative}.
+     * @hide
+     */
+    public CameraMetadataNative getNativeCopy() {
+        return new CameraMetadataNative(mProperties);
+    }
+
     @Override
     public <T> T get(Key<T> key) {
         return mProperties.get(key);
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d79f4b0..f91fcb9 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -33,6 +33,8 @@
  * capture. The result also includes additional metadata about the state of the
  * camera device during the capture.</p>
  *
+ * <p>{@link CameraCharacteristics} objects are immutable.</p>
+ *
  */
 public final class CaptureResult extends CameraMetadata {
 
@@ -58,6 +60,14 @@
         mSequenceId = sequenceId;
     }
 
+    /**
+     * Returns a copy of the underlying {@link CameraMetadataNative}.
+     * @hide
+     */
+    public CameraMetadataNative getNativeCopy() {
+        return new CameraMetadataNative(mResults);
+    }
+
     @Override
     public <T> T get(Key<T> key) {
         return mResults.get(key);
diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java
index 9193f89..a71a74d 100644
--- a/core/java/android/hardware/hdmi/HdmiCec.java
+++ b/core/java/android/hardware/hdmi/HdmiCec.java
@@ -171,8 +171,15 @@
     public static final int POWER_STATUS_UNKNOWN = -1;
     public static final int POWER_STATUS_ON = 0;
     public static final int POWER_STATUS_STANDBY = 1;
-    public static final int POWER_TRANSIENT_TO_ON = 2;
-    public static final int POWER_TRANSIENT_TO_STANDBY = 3;
+    public static final int POWER_STATUS_TRANSIENT_TO_ON = 2;
+    public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3;
+
+    public static final int RESULT_SUCCESS = 0;
+    public static final int RESULT_TIMEOUT = 1;
+    public static final int RESULT_SOURCE_NOT_AVAILABLE = 2;
+    public static final int RESULT_TARGET_NOT_AVAILABLE = 3;
+    public static final int RESULT_ALREADY_IN_PROGRESS = 4;
+    public static final int RESULT_EXCEPTION = 5;
 
     private static final int[] ADDRESS_TO_TYPE = {
         DEVICE_TV,  // ADDR_TV
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
new file mode 100644
index 0000000..a3f27b9
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -0,0 +1,76 @@
+/*
+ * 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.hardware.hdmi;
+
+import android.annotation.Nullable;
+/**
+ * The {@link HdmiControlManager} class is used to send HDMI control messages
+ * to attached CEC devices.
+ *
+ * <p>Provides various HDMI client instances that represent HDMI-CEC logical devices
+ * hosted in the system. {@link #getTvClient()}, for instance will return an
+ * {@link HdmiTvClient} object if the system is configured to host one. Android system
+ * can host more than one logical CEC devices. If multiple types are configured they
+ * all work as if they were independent logical devices running in the system.
+ */
+public final class HdmiControlManager {
+    @Nullable private final IHdmiControlService mService;
+
+    /**
+     * @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;
+    }
+
+    /**
+     * Gets an object that represents a HDMI-CEC logical device of type playback on the system.
+     *
+     * <p>Used to send HDMI control messages to other devices like TV or audio amplifier through
+     * HDMI bus. It is also possible to communicate with other logical devices hosted in the same
+     * system if the system is configured to host more than one type of HDMI-CEC logical devices.
+     *
+     * @return {@link HdmiPlaybackClient} instance. {@code null} on failure.
+     */
+    @Nullable
+    public HdmiPlaybackClient getPlaybackClient() {
+        if (mService == null) {
+            return null;
+        }
+        return new HdmiPlaybackClient(mService);
+    }
+
+    /**
+     * Gets an object that represents a HDMI-CEC logical device of type TV on the system.
+     *
+     * <p>Used to send HDMI control messages to other devices and manage them through
+     * HDMI bus. It is also possible to communicate with other logical devices hosted in the same
+     * system if the system is configured to host more than one type of HDMI-CEC logical devices.
+     *
+     * @return {@link HdmiTvClient} instance. {@code null} on failure.
+     */
+    @Nullable
+    public HdmiTvClient getTvClient() {
+        if (mService == null) {
+            return null;
+        }
+        return new HdmiTvClient(mService);
+    }
+}
diff --git a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
new file mode 100644
index 0000000..83da29a
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
@@ -0,0 +1,116 @@
+/*
+ * 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.hardware.hdmi;
+
+import android.os.RemoteException;
+
+import android.util.Log;
+
+/**
+ * HdmiPlaybackClient represents HDMI-CEC logical device of type Playback
+ * in the Android system which acts as a playback device such as set-top box.
+ * It provides with methods that control, get information from TV/Display device
+ * connected through HDMI bus.
+ */
+public final class HdmiPlaybackClient {
+    private static final String TAG = "HdmiPlaybackClient";
+
+    private final IHdmiControlService mService;
+
+    /**
+     * Listener used by the client to get the result of one touch play operation.
+     */
+    public interface OneTouchPlayCallback {
+        /**
+         * Called when the result of the feature one touch play is returned.
+         *
+         * @param result the result of the operation. {@link HdmiCec#RESULT_SUCCESS}
+         *         if successful.
+         */
+        public void onComplete(int result);
+    }
+
+    /**
+     * Listener used by the client to get display device status.
+     */
+    public interface DisplayStatusCallback {
+        /**
+         * Called when display device status is reported.
+         *
+         * @param status display device status
+         * @see {@link HdmiCec#POWER_STATUS_ON}
+         * @see {@link HdmiCec#POWER_STATUS_STANDBY}
+         * @see {@link HdmiCec#POWER_STATUS_TRANSIENT_TO_ON}
+         * @see {@link HdmiCec#POWER_STATUS_TRANSIENT_TO_STANDBY}
+         * @see {@link HdmiCec#POWER_STATUS_UNKNOWN}
+         */
+        public void onComplete(int status);
+    }
+
+    HdmiPlaybackClient(IHdmiControlService service) {
+        mService = service;
+    }
+
+    /**
+     * Perform the feature 'one touch play' from playback device to turn on display
+     * and switch the input.
+     *
+     * @param callback {@link OneTouchPlayCallback} object to get informed
+     *         of the result
+     */
+    public void oneTouchPlay(OneTouchPlayCallback callback) {
+        // TODO: Use PendingResult.
+        try {
+            mService.oneTouchPlay(getCallbackWrapper(callback));
+        } catch (RemoteException e) {
+            Log.e(TAG, "oneTouchPlay threw exception ", e);
+        }
+    }
+
+    /**
+     * Get the status of display device connected through HDMI bus.
+     *
+     * @param callback {@link DisplayStatusCallback} object to get informed
+     *         of the result
+     */
+    public void queryDisplayStatus(DisplayStatusCallback callback) {
+        // TODO: PendingResult.
+        try {
+            mService.oneTouchPlay(getCallbackWrapper(callback));
+        } catch (RemoteException e) {
+            Log.e(TAG, "queryDisplayStatus threw exception ", e);
+        }
+    }
+
+    private IHdmiControlCallback getCallbackWrapper(final OneTouchPlayCallback callback) {
+        return new IHdmiControlCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                callback.onComplete(result);
+            }
+        };
+    }
+
+    private IHdmiControlCallback getCallbackWrapper(final DisplayStatusCallback callback) {
+        return new IHdmiControlCallback.Stub() {
+            @Override
+            public void onComplete(int status) {
+                callback.onComplete(status);
+            }
+        };
+    }
+}
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
new file mode 100644
index 0000000..73c72472
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.hdmi;
+
+/**
+ * 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
+ * devices on the CEC bus.
+ */
+public final class HdmiTvClient {
+    private static final String TAG = "HdmiTvClient";
+
+    private final IHdmiControlService mService;
+
+    HdmiTvClient(IHdmiControlService service) {
+        mService = service;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java b/core/java/android/hardware/hdmi/IHdmiControlCallback.aidl
similarity index 72%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java
copy to core/java/android/hardware/hdmi/IHdmiControlCallback.aidl
index 158e9c1..ef3dd47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java
+++ b/core/java/android/hardware/hdmi/IHdmiControlCallback.aidl
@@ -14,9 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.hardware.hdmi;
 
-/** Common interface for items requiring manual cleanup. **/
-public interface Disposable {
-    void dispose();
+/**
+ * Callback interface definition for HDMI client to get informed of
+ * the result of various API invocation.
+ *
+ * @hide
+ */
+oneway interface IHdmiControlCallback {
+    void onComplete(int result);
 }
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
new file mode 100644
index 0000000..f790ed9
--- /dev/null
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -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.
+ */
+
+package android.hardware.hdmi;
+
+import android.hardware.hdmi.HdmiCecMessage;
+import android.hardware.hdmi.IHdmiControlCallback;
+
+/**
+ * Binder interface that clients running in the application process
+ * will use to perform HDMI-CEC features by communicating with other devices
+ * on the bus.
+ *
+ * @hide
+ */
+interface IHdmiControlService {
+    int oneTouchPlay(IHdmiControlCallback callback);
+    int queryDisplayStatus(IHdmiControlCallback callback);
+}
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index a725bec..d07c0b61 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -39,7 +39,8 @@
  * <ul>
  * <li>An IP address and prefix length (e.g., {@code 2001:db8::1/64} or {@code 192.0.2.1/24}).
  * The address must be unicast, as multicast addresses cannot be assigned to interfaces.
- * <li>Address flags: A bitmask of {@code IFA_F_*} values representing properties of the address.
+ * <li>Address flags: A bitmask of {@code IFA_F_*} values representing properties
+ * of the address.
  * <li>Address scope: An integer defining the scope in which the address is unique (e.g.,
  * {@code RT_SCOPE_LINK} or {@code RT_SCOPE_SITE}).
  * <ul>
@@ -47,10 +48,9 @@
  * When constructing a {@code LinkAddress}, the IP address and prefix are required. The flags and
  * scope are optional. If they are not specified, the flags are set to zero, and the scope will be
  * determined based on the IP address (e.g., link-local addresses will be created with a scope of
- * {@code RT_SCOPE_LINK}, global addresses with {@code RT_SCOPE_UNIVERSE}, etc.) If they are
- * specified, they are not checked for validity.
+ * {@code RT_SCOPE_LINK}, global addresses with {@code RT_SCOPE_UNIVERSE},
+ * etc.) If they are specified, they are not checked for validity.
  *
- * @hide
  */
 public class LinkAddress implements Parcelable {
     /**
@@ -119,6 +119,10 @@
      * the specified flags and scope. Flags and scope are not checked for validity.
      * @param address The IP address.
      * @param prefixLength The prefix length.
+     * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address.
+     * @param scope An integer defining the scope in which the address is unique (e.g.,
+     *              {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}).
+     * @hide
      */
     public LinkAddress(InetAddress address, int prefixLength, int flags, int scope) {
         init(address, prefixLength, flags, scope);
@@ -129,6 +133,7 @@
      * The flags are set to zero and the scope is determined from the address.
      * @param address The IP address.
      * @param prefixLength The prefix length.
+     * @hide
      */
     public LinkAddress(InetAddress address, int prefixLength) {
         this(address, prefixLength, 0, 0);
@@ -139,6 +144,7 @@
      * Constructs a new {@code LinkAddress} from an {@code InterfaceAddress}.
      * The flags are set to zero and the scope is determined from the address.
      * @param interfaceAddress The interface address.
+     * @hide
      */
     public LinkAddress(InterfaceAddress interfaceAddress) {
         this(interfaceAddress.getAddress(),
@@ -149,6 +155,7 @@
      * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or
      * "2001:db8::1/64". The flags are set to zero and the scope is determined from the address.
      * @param string The string to parse.
+     * @hide
      */
     public LinkAddress(String address) {
         this(address, 0, 0);
@@ -161,6 +168,7 @@
      * @param string The string to parse.
      * @param flags The address flags.
      * @param scope The address scope.
+     * @hide
      */
     public LinkAddress(String address, int flags, int scope) {
         InetAddress inetAddress = null;
@@ -220,9 +228,10 @@
     }
 
     /**
-     * Determines whether this {@code LinkAddress} and the provided {@code LinkAddress} represent
-     * the same address. Two LinkAddresses represent the same address if they have the same IP
-     * address and prefix length, even if their properties are different.
+     * Determines whether this {@code LinkAddress} and the provided {@code LinkAddress}
+     * represent the same address. Two {@code LinkAddresses} represent the same address
+     * if they have the same IP address and prefix length, even if their properties are
+     * different.
      *
      * @param other the {@code LinkAddress} to compare to.
      * @return {@code true} if both objects have the same address and prefix length, {@code false}
@@ -233,28 +242,28 @@
     }
 
     /**
-     * Returns the InetAddress of this address.
+     * Returns the {@link InetAddress} of this {@code LinkAddress}.
      */
     public InetAddress getAddress() {
         return address;
     }
 
     /**
-     * Returns the prefix length of this address.
+     * Returns the prefix length of this {@code LinkAddress}.
      */
     public int getNetworkPrefixLength() {
         return prefixLength;
     }
 
     /**
-     * Returns the flags of this address.
+     * Returns the flags of this {@code LinkAddress}.
      */
     public int getFlags() {
         return flags;
     }
 
     /**
-     * Returns the scope of this address.
+     * Returns the scope of this {@code LinkAddress}.
      */
     public int getScope() {
         return scope;
@@ -262,6 +271,7 @@
 
     /**
      * Returns true if this {@code LinkAddress} is global scope and preferred.
+     * @hide
      */
     public boolean isGlobalPreferred() {
         return (scope == RT_SCOPE_UNIVERSE &&
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 489b8a5..3c36679 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -36,27 +36,12 @@
  *
  * A link represents a connection to a network.
  * It may have multiple addresses and multiple gateways,
- * multiple dns servers but only one http proxy.
+ * multiple dns servers but only one http proxy and one
+ * network interface.
  *
- * Because it's a single network, the dns's
- * are interchangeable and don't need associating with
- * particular addresses.  The gateways similarly don't
- * need associating with particular addresses.
+ * Note that this is just a holder of data.  Modifying it
+ * does not affect live networks.
  *
- * A dual stack interface works fine in this model:
- * each address has it's own prefix length to describe
- * the local network.  The dns servers all return
- * both v4 addresses and v6 addresses regardless of the
- * address family of the server itself (rfc4213) and we
- * don't care which is used.  The gateways will be
- * selected based on the destination address and the
- * source address has no relavence.
- *
- * Links can also be stacked on top of each other.
- * This can be used, for example, to represent a tunnel
- * interface that runs on top of a physical interface.
- *
- * @hide
  */
 public class LinkProperties implements Parcelable {
     // The interface described by the network link.
@@ -73,6 +58,7 @@
     private Hashtable<String, LinkProperties> mStackedLinks =
         new Hashtable<String, LinkProperties>();
 
+    // @hide
     public static class CompareResult<T> {
         public Collection<T> removed = new ArrayList<T>();
         public Collection<T> added = new ArrayList<T>();
@@ -91,7 +77,6 @@
     public LinkProperties() {
     }
 
-    // copy constructor instead of clone
     public LinkProperties(LinkProperties source) {
         if (source != null) {
             mIfaceName = source.getInterfaceName();
@@ -108,6 +93,12 @@
         }
     }
 
+    /**
+     * Sets the interface name for this link.  All {@link RouteInfo} already set for this
+     * will have their interface changed to match this new value.
+     *
+     * @param iface The name of the network interface used for this link.
+     */
     public void setInterfaceName(String iface) {
         mIfaceName = iface;
         ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size());
@@ -117,10 +108,16 @@
         mRoutes = newRoutes;
     }
 
+    /**
+     * Gets the interface name for this link.  May be {@code null} if not set.
+     *
+     * @return The interface name set for this link or {@code null}.
+     */
     public String getInterfaceName() {
         return mIfaceName;
     }
 
+    // @hide
     public Collection<String> getAllInterfaceNames() {
         Collection interfaceNames = new ArrayList<String>(mStackedLinks.size() + 1);
         if (mIfaceName != null) interfaceNames.add(new String(mIfaceName));
@@ -131,7 +128,14 @@
     }
 
     /**
-     * Returns all the addresses on this link.
+     * Returns all the addresses on this link.  We often think of a link having a single address,
+     * however, particularly with Ipv6 several addresses are typical.  Note that the
+     * {@code LinkProperties} actually contains {@link LinkAddress} objects which also include
+     * prefix lengths for each address.  This is a simplified utility alternative to
+     * {@link LinkProperties#getLinkAddresses}.
+     *
+     * @return An umodifiable {@link Collection} of {@link InetAddress} for this link.
+     * @hide
      */
     public Collection<InetAddress> getAddresses() {
         Collection<InetAddress> addresses = new ArrayList<InetAddress>();
@@ -143,6 +147,7 @@
 
     /**
      * Returns all the addresses on this link and all the links stacked above it.
+     * @hide
      */
     public Collection<InetAddress> getAllAddresses() {
         Collection<InetAddress> addresses = new ArrayList<InetAddress>();
@@ -165,7 +170,8 @@
     }
 
     /**
-     * Adds a link address if it does not exist, or updates it if it does.
+     * Adds a {@link LinkAddress} to this {@code LinkProperties} if a {@link LinkAddress} of the
+     * same address/prefix does not already exist.  If it does exist it is replaced.
      * @param address The {@code LinkAddress} to add.
      * @return true if {@code address} was added or updated, false otherwise.
      */
@@ -189,9 +195,10 @@
     }
 
     /**
-     * Removes a link address. Specifically, removes the link address, if any, for which
-     * {@code isSameAddressAs(toRemove)} returns true.
-     * @param address A {@code LinkAddress} specifying the address to remove.
+     * Removes a {@link LinkAddress} from this {@code LinkProperties}.  Specifically, matches
+     * and {@link LinkAddress} with the same address and prefix.
+     *
+     * @param toRemove A {@link LinkAddress} specifying the address to remove.
      * @return true if the address was removed, false if it did not exist.
      */
     public boolean removeLinkAddress(LinkAddress toRemove) {
@@ -204,7 +211,10 @@
     }
 
     /**
-     * Returns all the addresses on this link.
+     * Returns all the {@link LinkAddress} on this link.  Typically a link will have
+     * one IPv4 address and one or more IPv6 addresses.
+     *
+     * @return An unmodifiable {@link Collection} of {@link LinkAddress} for this link.
      */
     public Collection<LinkAddress> getLinkAddresses() {
         return Collections.unmodifiableCollection(mLinkAddresses);
@@ -212,6 +222,7 @@
 
     /**
      * Returns all the addresses on this link and all the links stacked above it.
+     * @hide
      */
     public Collection<LinkAddress> getAllLinkAddresses() {
         Collection<LinkAddress> addresses = new ArrayList<LinkAddress>();
@@ -223,7 +234,11 @@
     }
 
     /**
-     * Replaces the LinkAddresses on this link with the given collection of addresses.
+     * Replaces the {@link LinkAddress} in this {@code LinkProperties} with
+     * the given {@link Collection} of {@link LinkAddress}.
+     *
+     * @param addresses The {@link Collection} of {@link LinkAddress} to set in this
+     *                  object.
      */
     public void setLinkAddresses(Collection<LinkAddress> addresses) {
         mLinkAddresses.clear();
@@ -232,26 +247,64 @@
         }
     }
 
+    /**
+     * Adds the given {@link InetAddress} to the list of DNS servers.
+     *
+     * @param dns The {@link InetAddress} to add to the list of DNS servers.
+     */
     public void addDns(InetAddress dns) {
         if (dns != null) mDnses.add(dns);
     }
 
+    /**
+     * Returns all the {@link LinkAddress} for DNS servers on this link.
+     *
+     * @return An umodifiable {@link Collection} of {@link InetAddress} for DNS servers on
+     *         this link.
+     */
     public Collection<InetAddress> getDnses() {
         return Collections.unmodifiableCollection(mDnses);
     }
 
-    public String getDomains() {
-        return mDomains;
-    }
-
+    /**
+     * Sets the DNS domain search path used on this link.
+     *
+     * @param domains A {@link String} listing in priority order the comma separated
+     *                domains to search when resolving host names on this link.
+     */
     public void setDomains(String domains) {
         mDomains = domains;
     }
 
+    /**
+     * Get the DNS domains search path set for this link.
+     *
+     * @return A {@link String} containing the comma separated domains to search when resolving
+     *         host names on this link.
+     */
+    public String getDomains() {
+        return mDomains;
+    }
+
+    /**
+     * Sets the Maximum Transmission Unit size to use on this link.  This should not be used
+     * unless the system default (1500) is incorrect.  Values less than 68 or greater than
+     * 10000 will be ignored.
+     *
+     * @param mtu The MTU to use for this link.
+     * @hide
+     */
     public void setMtu(int mtu) {
         mMtu = mtu;
     }
 
+    /**
+     * Gets any non-default MTU size set for this link.  Note that if the default is being used
+     * this will return 0.
+     *
+     * @return The mtu value set for this link.
+     * @hide
+     */
     public int getMtu() {
         return mMtu;
     }
@@ -263,6 +316,14 @@
             mIfaceName);
     }
 
+    /**
+     * Adds a {@link RouteInfo} to this {@code LinkProperties}.  If the {@link RouteInfo}
+     * had an interface name set and that differs from the interface set for this
+     * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown.  The
+     * proper course is to add either un-named or properly named {@link RouteInfo}.
+     *
+     * @param route A {@link RouteInfo} to add to this object.
+     */
     public void addRoute(RouteInfo route) {
         if (route != null) {
             String routeIface = route.getInterface();
@@ -276,7 +337,9 @@
     }
 
     /**
-     * Returns all the routes on this link.
+     * Returns all the {@link RouteInfo} set on this link.
+     *
+     * @return An unmodifiable {@link Collection} of {@link RouteInfo} for this link.
      */
     public Collection<RouteInfo> getRoutes() {
         return Collections.unmodifiableCollection(mRoutes);
@@ -284,6 +347,7 @@
 
     /**
      * Returns all the routes on this link and all the links stacked above it.
+     * @hide
      */
     public Collection<RouteInfo> getAllRoutes() {
         Collection<RouteInfo> routes = new ArrayList();
@@ -294,9 +358,22 @@
         return routes;
     }
 
+    /**
+     * Sets the recommended {@link ProxyInfo} to use on this link, or {@code null} for none.
+     * Note that Http Proxies are only a hint - the system recommends their use, but it does
+     * not enforce it and applications may ignore them.
+     *
+     * @param proxy A {@link ProxyInfo} defining the Http Proxy to use on this link.
+     */
     public void setHttpProxy(ProxyInfo proxy) {
         mHttpProxy = proxy;
     }
+
+    /**
+     * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link.
+     *
+     * @return The {@link ProxyInfo} set on this link
+     */
     public ProxyInfo getHttpProxy() {
         return mHttpProxy;
     }
@@ -310,6 +387,7 @@
      *
      * @param link The link to add.
      * @return true if the link was stacked, false otherwise.
+     * @hide
      */
     public boolean addStackedLink(LinkProperties link) {
         if (link != null && link.getInterfaceName() != null) {
@@ -327,6 +405,7 @@
      *
      * @param link The link to remove.
      * @return true if the link was removed, false otherwise.
+     * @hide
      */
     public boolean removeStackedLink(LinkProperties link) {
         if (link != null && link.getInterfaceName() != null) {
@@ -338,6 +417,7 @@
 
     /**
      * Returns all the links stacked on top of this link.
+     * @hide
      */
     public Collection<LinkProperties> getStackedLinks() {
         Collection<LinkProperties> stacked = new ArrayList<LinkProperties>();
@@ -347,6 +427,9 @@
         return Collections.unmodifiableCollection(stacked);
     }
 
+    /**
+     * Clears this object to its initial state.
+     */
     public void clear() {
         mIfaceName = null;
         mLinkAddresses.clear();
@@ -432,6 +515,7 @@
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
      */
     public boolean isIdenticalInterfaceName(LinkProperties target) {
         return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
@@ -442,6 +526,7 @@
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
      */
     public boolean isIdenticalAddresses(LinkProperties target) {
         Collection<InetAddress> targetAddresses = target.getAddresses();
@@ -455,6 +540,7 @@
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
      */
     public boolean isIdenticalDnses(LinkProperties target) {
         Collection<InetAddress> targetDnses = target.getDnses();
@@ -473,6 +559,7 @@
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
      */
     public boolean isIdenticalRoutes(LinkProperties target) {
         Collection<RouteInfo> targetRoutes = target.getRoutes();
@@ -485,6 +572,7 @@
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
      */
     public boolean isIdenticalHttpProxy(LinkProperties target) {
         return getHttpProxy() == null ? target.getHttpProxy() == null :
@@ -496,6 +584,7 @@
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
      */
     public boolean isIdenticalStackedLinks(LinkProperties target) {
         if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
@@ -516,6 +605,7 @@
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
      */
     public boolean isIdenticalMtu(LinkProperties target) {
         return getMtu() == target.getMtu();
@@ -533,10 +623,6 @@
      * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
      * 2. Worst case performance is O(n^2).
      *
-     * This method does not check that stacked interfaces are equal, because
-     * stacked interfaces are not so much a property of the link as a
-     * description of connections between links.
-     *
      * @param obj the object to be tested for equality.
      * @return {@code true} if both objects are equal, {@code false} otherwise.
      */
@@ -546,7 +632,11 @@
         if (!(obj instanceof LinkProperties)) return false;
 
         LinkProperties target = (LinkProperties) obj;
-
+        /**
+         * This method does not check that stacked interfaces are equal, because
+         * stacked interfaces are not so much a property of the link as a
+         * description of connections between links.
+         */
         return isIdenticalInterfaceName(target) &&
                 isIdenticalAddresses(target) &&
                 isIdenticalDnses(target) &&
@@ -562,6 +652,7 @@
      *
      * @param target a LinkProperties with the new list of addresses
      * @return the differences between the addresses.
+     * @hide
      */
     public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
         /*
@@ -590,6 +681,7 @@
      *
      * @param target a LinkProperties with the new list of dns addresses
      * @return the differences between the DNS addresses.
+     * @hide
      */
     public CompareResult<InetAddress> compareDnses(LinkProperties target) {
         /*
@@ -619,6 +711,7 @@
      *
      * @param target a LinkProperties with the new list of routes
      * @return the differences between the routes.
+     * @hide
      */
     public CompareResult<RouteInfo> compareAllRoutes(LinkProperties target) {
         /*
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index ac1289b..a99da78 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -20,20 +20,35 @@
 import android.os.Parcel;
 
 import java.net.InetAddress;
+import java.net.Socket;
 import java.net.UnknownHostException;
+import javax.net.SocketFactory;
 
 /**
- * Identifies the Network.
+ * Identifies a {@code Network}.  This is supplied to applications via
+ * {@link ConnectivityManager#NetworkCallbacks} in response to
+ * {@link ConnectivityManager#requestNetwork} or {@link ConnectivityManager#listenForNetwork}.
+ * It is used to direct traffic to the given {@code Network}, either on a {@link Socket} basis
+ * through a targeted {@link SocketFactory} or process-wide via {@link #bindProcess}.
  * @hide
  */
 public class Network implements Parcelable {
 
+    /**
+     * @hide
+     */
     public final int netId;
 
+    /**
+     * @hide
+     */
     public Network(int netId) {
         this.netId = netId;
     }
 
+    /**
+     * @hide
+     */
     public Network(Network that) {
         this.netId = that.netId;
     }
@@ -64,6 +79,45 @@
         return InetAddress.getByNameOnNet(host, netId);
     }
 
+    /**
+     * Returns a {@link SocketFactory} bound to this network.  Any {@link Socket} created by
+     * this factory will have its traffic sent over this {@code Network}.  Note that if this
+     * {@code Network} ever disconnects, this factory and any {@link Socket} it produced in the
+     * past or future will cease to work.
+     *
+     * @return a {@link SocketFactory} which produces {@link Socket} instances bound to this
+     *         {@code Network}.
+     */
+    public SocketFactory socketFactory() {
+        return null;
+    }
+
+    /**
+     * Binds the current process to this network.  All sockets created in the future (and not
+     * explicitly bound via a bound {@link SocketFactory} (see {@link Network#socketFactory})
+     * will be bound to this network.  Note that if this {@code Network} ever disconnects
+     * all sockets created in this way will cease to work.  This is by design so an application
+     * doesn't accidentally use sockets it thinks are still bound to a particular {@code Network}.
+     */
+    public void bindProcess() {
+    }
+
+    /**
+     * A static utility method to return any {@code Network} currently bound by this process.
+     *
+     * @return {@code Network} to which this process is bound.
+     */
+    public static Network getProcessBoundNetwork() {
+        return null;
+    }
+
+    /**
+     * Clear any process specific {@code Network} binding.  This reverts a call to
+     * {@link Network#bindProcess}.
+     */
+    public static void unbindProcess() {
+    }
+
     // implement the Parcelable interface
     public int describeContents() {
         return 0;
@@ -84,4 +138,14 @@
                 return new Network[size];
             }
     };
+
+    public boolean equals(Object obj) {
+        if (obj instanceof Network == false) return false;
+        Network other = (Network)obj;
+        return this.netId == other.netId;
+    }
+
+    public int hashCode() {
+        return netId * 11;
+    }
 }
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8005e5c..35274f1 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -30,13 +30,31 @@
 import java.util.Set;
 
 /**
- * A class representing the capabilities of a network
- * @hide
+ * This class represents the capabilities of a network.  This is used both to specify
+ * needs to {@link ConnectivityManager} and when inspecting a network.
+ *
+ * Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method
+ * of network selection.  Rather than indicate a need for Wi-Fi because an application
+ * needs high bandwidth and risk obselence when a new, fast network appears (like LTE),
+ * the application should specify it needs high bandwidth.  Similarly if an application
+ * needs an unmetered network for a bulk transfer it can specify that rather than assuming
+ * all cellular based connections are metered and all Wi-Fi based connections are not.
  */
 public final class NetworkCapabilities implements Parcelable {
     private static final String TAG = "NetworkCapabilities";
     private static final boolean DBG = false;
 
+    public NetworkCapabilities() {
+    }
+
+    public NetworkCapabilities(NetworkCapabilities nc) {
+        if (nc != null) {
+            mNetworkCapabilities = nc.mNetworkCapabilities;
+            mTransportTypes = nc.mTransportTypes;
+            mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
+            mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
+        }
+    }
 
     /**
      * Represents the network's capabilities.  If any are specified they will be satisfied
@@ -45,28 +63,99 @@
     private long mNetworkCapabilities = (1 << NET_CAPABILITY_NOT_RESTRICTED);
 
     /**
-     * Values for NetworkCapabilities.  Roughly matches/extends deprecated
-     * ConnectivityManager TYPE_*
+     * Indicates this is a network that has the ability to reach the
+     * carrier's MMSC for sending and receiving MMS messages.
      */
     public static final int NET_CAPABILITY_MMS            = 0;
+
+    /**
+     * Indicates this is a network that has the ability to reach the carrier's
+     * SUPL server, used to retrieve GPS information.
+     */
     public static final int NET_CAPABILITY_SUPL           = 1;
+
+    /**
+     * Indicates this is a network that has the ability to reach the carrier's
+     * DUN or tethering gateway.
+     */
     public static final int NET_CAPABILITY_DUN            = 2;
+
+    /**
+     * Indicates this is a network that has the ability to reach the carrier's
+     * FOTA portal, used for over the air updates.
+     */
     public static final int NET_CAPABILITY_FOTA           = 3;
+
+    /**
+     * Indicates this is a network that has the ability to reach the carrier's
+     * IMS servers, used for network registration and signaling.
+     */
     public static final int NET_CAPABILITY_IMS            = 4;
+
+    /**
+     * Indicates this is a network that has the ability to reach the carrier's
+     * CBS servers, used for carrier specific services.
+     */
     public static final int NET_CAPABILITY_CBS            = 5;
+
+    /**
+     * Indicates this is a network that has the ability to reach a Wi-Fi direct
+     * peer.
+     */
     public static final int NET_CAPABILITY_WIFI_P2P       = 6;
+
+    /**
+     * Indicates this is a network that has the ability to reach a carrier's
+     * Initial Attach servers.
+     */
     public static final int NET_CAPABILITY_IA             = 7;
+
+    /**
+     * Indicates this is a network that has the ability to reach a carrier's
+     * RCS servers, used for Rich Communication Services.
+     */
     public static final int NET_CAPABILITY_RCS            = 8;
+
+    /**
+     * Indicates this is a network that has the ability to reach a carrier's
+     * XCAP servers, used for configuration and control.
+     */
     public static final int NET_CAPABILITY_XCAP           = 9;
+
+    /**
+     * Indicates this is a network that has the ability to reach a carrier's
+     * Emergency IMS servers, used for network signaling during emergency calls.
+     */
     public static final int NET_CAPABILITY_EIMS           = 10;
+
+    /**
+     * Indicates that this network is unmetered.
+     */
     public static final int NET_CAPABILITY_NOT_METERED    = 11;
+
+    /**
+     * Indicates that this network should be able to reach the internet.
+     */
     public static final int NET_CAPABILITY_INTERNET       = 12;
-    /** Set by default */
+
+    /**
+     * Indicates that this network is available for general use.  If this is not set
+     * applications should not attempt to communicate on this network.  Note that this
+     * is simply informative and not enforcement - enforcement is handled via other means.
+     * Set by default.
+     */
     public static final int NET_CAPABILITY_NOT_RESTRICTED = 13;
 
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
     private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_RESTRICTED;
 
+    /**
+     * Adds the given capability to this {@code NetworkCapability} instance.
+     * Multiple capabilities may be applied sequentially.  Note that when searching
+     * for a network to satisfy a request, all capabilities requested must be satisfied.
+     *
+     * @param networkCapability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
+     */
     public void addNetworkCapability(int networkCapability) {
         if (networkCapability < MIN_NET_CAPABILITY ||
                 networkCapability > MAX_NET_CAPABILITY) {
@@ -74,6 +163,12 @@
         }
         mNetworkCapabilities |= 1 << networkCapability;
     }
+
+    /**
+     * Removes (if found) the given capability from this {@code NetworkCapability} instance.
+     *
+     * @param networkCapability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
+     */
     public void removeNetworkCapability(int networkCapability) {
         if (networkCapability < MIN_NET_CAPABILITY ||
                 networkCapability > MAX_NET_CAPABILITY) {
@@ -81,9 +176,23 @@
         }
         mNetworkCapabilities &= ~(1 << networkCapability);
     }
+
+    /**
+     * Gets all the capabilities set on this {@code NetworkCapability} instance.
+     *
+     * @return a {@link Collection} of {@code NetworkCapabilities.NET_CAPABILITY_*} values
+     *         for this instance.
+     */
     public Collection<Integer> getNetworkCapabilities() {
         return enumerateBits(mNetworkCapabilities);
     }
+
+    /**
+     * Tests for the presence of a capabilitity on this instance.
+     *
+     * @param networkCapability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be tested for.
+     * @return {@code true} if set on this instance.
+     */
     public boolean hasCapability(int networkCapability) {
         if (networkCapability < MIN_NET_CAPABILITY ||
                 networkCapability > MAX_NET_CAPABILITY) {
@@ -124,31 +233,74 @@
     private long mTransportTypes;
 
     /**
-     * Values for TransportType
+     * Indicates this network uses a Cellular transport.
      */
     public static final int TRANSPORT_CELLULAR = 0;
+
+    /**
+     * Indicates this network uses a Wi-Fi transport.
+     */
     public static final int TRANSPORT_WIFI = 1;
+
+    /**
+     * Indicates this network uses a Bluetooth transport.
+     */
     public static final int TRANSPORT_BLUETOOTH = 2;
+
+    /**
+     * Indicates this network uses an Ethernet transport.
+     */
     public static final int TRANSPORT_ETHERNET = 3;
 
     private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
     private static final int MAX_TRANSPORT = TRANSPORT_ETHERNET;
 
+    /**
+     * Adds the given transport type to this {@code NetworkCapability} instance.
+     * Multiple transports may be applied sequentially.  Note that when searching
+     * for a network to satisfy a request, any listed in the request will satisfy the request.
+     * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a
+     * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network
+     * to be selected.  This is logically different than
+     * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
+     *
+     * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be added.
+     */
     public void addTransportType(int transportType) {
         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
             throw new IllegalArgumentException("TransportType out of range");
         }
         mTransportTypes |= 1 << transportType;
     }
+
+    /**
+     * Removes (if found) the given transport from this {@code NetworkCapability} instance.
+     *
+     * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be removed.
+     */
     public void removeTransportType(int transportType) {
         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
             throw new IllegalArgumentException("TransportType out of range");
         }
         mTransportTypes &= ~(1 << transportType);
     }
+
+    /**
+     * Gets all the transports set on this {@code NetworkCapability} instance.
+     *
+     * @return a {@link Collection} of {@code NetworkCapabilities.TRANSPORT_*} values
+     *         for this instance.
+     */
     public Collection<Integer> getTransportTypes() {
         return enumerateBits(mTransportTypes);
     }
+
+    /**
+     * Tests for the presence of a transport on this instance.
+     *
+     * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be tested for.
+     * @return {@code true} if set on this instance.
+     */
     public boolean hasTransport(int transportType) {
         if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
             return false;
@@ -175,15 +327,58 @@
     private int mLinkUpBandwidthKbps;
     private int mLinkDownBandwidthKbps;
 
+    /**
+     * Sets the upstream bandwidth for this network in Kbps.  This always only refers to
+     * the estimated first hop transport bandwidth.
+     * <p>
+     * Note that when used to request a network, this specifies the minimum acceptable.
+     * When received as the state of an existing network this specifies the typical
+     * first hop bandwidth expected.  This is never measured, but rather is inferred
+     * from technology type and other link parameters.  It could be used to differentiate
+     * between very slow 1xRTT cellular links and other faster networks or even between
+     * 802.11b vs 802.11AC wifi technologies.  It should not be used to differentiate between
+     * fast backhauls and slow backhauls.
+     *
+     * @param upKbps the estimated first hop upstream (device to network) bandwidth.
+     */
     public void setLinkUpstreamBandwidthKbps(int upKbps) {
         mLinkUpBandwidthKbps = upKbps;
     }
+
+    /**
+     * Retrieves the upstream bandwidth for this network in Kbps.  This always only refers to
+     * the estimated first hop transport bandwidth.
+     *
+     * @return The estimated first hop upstream (device to network) bandwidth.
+     */
     public int getLinkUpstreamBandwidthKbps() {
         return mLinkUpBandwidthKbps;
     }
+
+    /**
+     * Sets the downstream bandwidth for this network in Kbps.  This always only refers to
+     * the estimated first hop transport bandwidth.
+     * <p>
+     * Note that when used to request a network, this specifies the minimum acceptable.
+     * When received as the state of an existing network this specifies the typical
+     * first hop bandwidth expected.  This is never measured, but rather is inferred
+     * from technology type and other link parameters.  It could be used to differentiate
+     * between very slow 1xRTT cellular links and other faster networks or even between
+     * 802.11b vs 802.11AC wifi technologies.  It should not be used to differentiate between
+     * fast backhauls and slow backhauls.
+     *
+     * @param downKbps the estimated first hop downstream (network to device) bandwidth.
+     */
     public void setLinkDownstreamBandwidthKbps(int downKbps) {
         mLinkDownBandwidthKbps = downKbps;
     }
+
+    /**
+     * Retrieves the downstream bandwidth for this network in Kbps.  This always only refers to
+     * the estimated first hop transport bandwidth.
+     *
+     * @return The estimated first hop downstream (network to device) bandwidth.
+     */
     public int getLinkDownstreamBandwidthKbps() {
         return mLinkDownBandwidthKbps;
     }
@@ -243,19 +438,6 @@
                 (mLinkDownBandwidthKbps * 13));
     }
 
-    public NetworkCapabilities() {
-    }
-
-    public NetworkCapabilities(NetworkCapabilities nc) {
-        if (nc != null) {
-            mNetworkCapabilities = nc.mNetworkCapabilities;
-            mTransportTypes = nc.mTransportTypes;
-            mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
-            mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
-        }
-    }
-
-    // Parcelable
     public int describeContents() {
         return 0;
     }
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index b3ae3f5..80074a5 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -22,11 +22,19 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
+ * Defines a request for a network, made by calling {@link ConnectivityManager.requestNetwork}.
+ *
+ * This token records the {@link NetworkCapabilities} used to make the request and identifies
+ * the request.  It should be used to release the request via
+ * {@link ConnectivityManager.releaseNetworkRequest} when the network is no longer desired.
  * @hide
  */
 public class NetworkRequest implements Parcelable {
     /**
-     * The NetworkCapabilities that define this request
+     * The {@link NetworkCapabilities} that define this request.  This should not be modified.
+     * The networkCapabilities of the request are set when
+     * {@link ConnectivityManager.requestNetwork} is called and the value is presented here
+     * as a convenient reminder of what was requested.
      */
     public final NetworkCapabilities networkCapabilities;
 
@@ -34,7 +42,7 @@
      * Identifies the request.  NetworkRequests should only be constructed by
      * the Framework and given out to applications as tokens to be used to identify
      * the request.
-     * TODO - make sure this input is checked whenever a NR is passed in a public API
+     * @hide
      */
     public final int requestId;
 
@@ -45,31 +53,18 @@
      */
     public final boolean needsBroadcasts;
 
-    private static final AtomicInteger sNextRequestId = new AtomicInteger(1);
-
     /**
      * @hide
      */
-    public NetworkRequest(NetworkCapabilities nc) {
-        this(nc, false, sNextRequestId.getAndIncrement());
-    }
-
-    /**
-     * @hide
-     */
-    public NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts) {
-        this(nc, needsBroadcasts, sNextRequestId.getAndIncrement());
-    }
-
-    /**
-     * @hide
-     */
-    private NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts, int rId) {
+    public NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts, int rId) {
         requestId = rId;
         networkCapabilities = nc;
         this.needsBroadcasts = needsBroadcasts;
     }
 
+    /**
+     * @hide
+     */
     public NetworkRequest(NetworkRequest that) {
         networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
         requestId = that.requestId;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 1d051dd..ad8e4f7 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -25,22 +25,26 @@
 import java.net.Inet6Address;
 
 import java.util.Collection;
+import java.util.Objects;
 
 /**
- * A simple container for route information.
+ * Represents a network route.
+ * <p>
+ * This is used both to describe static network configuration and live network
+ * configuration information.
  *
- * In order to be used, a route must have a destination prefix and:
- *
- * - A gateway address (next-hop, for gatewayed routes), or
- * - An interface (for directly-connected routes), or
- * - Both a gateway and an interface.
- *
- * This class does not enforce these constraints because there is code that
- * uses RouteInfo objects to store directly-connected routes without interfaces.
- * Such objects cannot be used directly, but can be put into a LinkProperties
- * object which then specifies the interface.
- *
- * @hide
+ * A route contains three pieces of information:
+ * <ul>
+ * <li>a destination {@link LinkAddress} for directly-connected subnets.  If this is
+ *     {@code null} it indicates a default route of the address family (IPv4 or IPv6)
+ *     implied by the gateway IP address.
+ * <li>a gateway {@link InetAddress} for default routes.  If this is {@code null} it
+ *     indicates a directly-connected route.
+ * <li>an interface (which may be unspecified).
+ * </ul>
+ * Either the destination or the gateway may be {@code null}, but not both.  If the
+ * destination and gateway are both specified, they must be of the same address family
+ * (IPv4 or IPv6).
  */
 public class RouteInfo implements Parcelable {
     /**
@@ -67,10 +71,10 @@
      *
      * If destination is null, then gateway must be specified and the
      * constructed route is either the IPv4 default route <code>0.0.0.0</code>
-     * if @gateway is an instance of {@link Inet4Address}, or the IPv6 default
+     * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
      * route <code>::/0</code> if gateway is an instance of
      * {@link Inet6Address}.
-     *
+     * <p>
      * destination and gateway may not both be null.
      *
      * @param destination the destination prefix
@@ -102,28 +106,64 @@
 
         mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
                 destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
+        if ((destination.getAddress() instanceof Inet4Address &&
+                 (gateway instanceof Inet4Address == false)) ||
+                (destination.getAddress() instanceof Inet6Address &&
+                 (gateway instanceof Inet6Address == false))) {
+            throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
+        }
         mGateway = gateway;
         mInterface = iface;
         mIsDefault = isDefault();
         mIsHost = isHost();
     }
 
+    /**
+     * Constructs a {@code RouteInfo} object.
+     *
+     * If destination is null, then gateway must be specified and the
+     * constructed route is either the IPv4 default route <code>0.0.0.0</code>
+     * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
+     * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
+     * <p>
+     * Destination and gateway may not both be null.
+     *
+     * @param destination the destination address and prefix in a {@link LinkAddress}
+     * @param gateway the {@link InetAddress} to route packets through
+     */
     public RouteInfo(LinkAddress destination, InetAddress gateway) {
         this(destination, gateway, null);
     }
 
+    /**
+     * Constructs a default {@code RouteInfo} object.
+     *
+     * @param gateway the {@link InetAddress} to route packets through
+     */
     public RouteInfo(InetAddress gateway) {
         this(null, gateway, null);
     }
 
-    public RouteInfo(LinkAddress host) {
-        this(host, null, null);
+    /**
+     * Constructs a {@code RouteInfo} object representing a direct connected subnet.
+     *
+     * @param destination the {@link LinkAddress} describing the address and prefix
+     *                    length of the subnet.
+     */
+    public RouteInfo(LinkAddress destination) {
+        this(destination, null, null);
     }
 
+    /**
+     * @hide
+     */
     public static RouteInfo makeHostRoute(InetAddress host, String iface) {
         return makeHostRoute(host, null, iface);
     }
 
+    /**
+     * @hide
+     */
     public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway, String iface) {
         if (host == null) return null;
 
@@ -153,31 +193,108 @@
         return val;
     }
 
-
+    /**
+     * Retrieves the destination address and prefix length in the form of a {@link LinkAddress}.
+     *
+     * @return {@link LinkAddress} specifying the destination.  This is never {@code null}.
+     */
     public LinkAddress getDestination() {
         return mDestination;
     }
 
+    /**
+     * Retrieves the gateway or next hop {@link InetAddress} for this route.
+     *
+     * @return {@link InetAddress} specifying the gateway or next hop.  This may be
+     &                             {@code null} for a directly-connected route."
+     */
     public InetAddress getGateway() {
         return mGateway;
     }
 
+    /**
+     * Retrieves the interface used for this route if specified, else {@code null}.
+     *
+     * @return The name of the interface used for this route.
+     */
     public String getInterface() {
         return mInterface;
     }
 
+    /**
+     * Indicates if this route is a default route (ie, has no destination specified).
+     *
+     * @return {@code true} if the destination has a prefix length of 0.
+     */
     public boolean isDefaultRoute() {
         return mIsDefault;
     }
 
+    /**
+     * Indicates if this route is a host route (ie, matches only a single host address).
+     *
+     * @return {@code true} if the destination has a prefix length of 32/128 for v4/v6.
+     * @hide
+     */
     public boolean isHostRoute() {
         return mIsHost;
     }
 
+    /**
+     * Indicates if this route has a next hop ({@code true}) or is directly-connected
+     * ({@code false}).
+     *
+     * @return {@code true} if a gateway is specified
+     * @hide
+     */
     public boolean hasGateway() {
         return mHasGateway;
     }
 
+    /**
+     * Determines whether the destination and prefix of this route includes the specified
+     * address.
+     *
+     * @param destination A {@link InetAddress} to test to see if it would match this route.
+     * @return {@code true} if the destination and prefix length cover the given address.
+     */
+    public boolean matches(InetAddress destination) {
+        if (destination == null) return false;
+
+        // match the route destination and destination with prefix length
+        InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
+                mDestination.getNetworkPrefixLength());
+
+        return mDestination.getAddress().equals(dstNet);
+    }
+
+    /**
+     * Find the route from a Collection of routes that best matches a given address.
+     * May return null if no routes are applicable.
+     * @param routes a Collection of RouteInfos to chose from
+     * @param dest the InetAddress your trying to get to
+     * @return the RouteInfo from the Collection that best fits the given address
+     *
+     * @hide
+     */
+    public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
+        if ((routes == null) || (dest == null)) return null;
+
+        RouteInfo bestRoute = null;
+        // pick a longest prefix match under same address type
+        for (RouteInfo route : routes) {
+            if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
+                if ((bestRoute != null) &&
+                        (bestRoute.mDestination.getNetworkPrefixLength() >=
+                        route.mDestination.getNetworkPrefixLength())) {
+                    continue;
+                }
+                if (route.matches(dest)) bestRoute = route;
+            }
+        }
+        return bestRoute;
+    }
+
     public String toString() {
         String val = "";
         if (mDestination != null) val = mDestination.toString();
@@ -185,10 +302,37 @@
         return val;
     }
 
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+
+        if (!(obj instanceof RouteInfo)) return false;
+
+        RouteInfo target = (RouteInfo) obj;
+
+        return Objects.equals(mDestination, target.getDestination()) &&
+                Objects.equals(mGateway, target.getGateway()) &&
+                Objects.equals(mInterface, target.getInterface());
+    }
+
+    public int hashCode() {
+        return (mDestination == null ? 0 : mDestination.hashCode() * 41)
+                + (mGateway == null ? 0 :mGateway.hashCode() * 47)
+                + (mInterface == null ? 0 :mInterface.hashCode() * 67)
+                + (mIsDefault ? 3 : 7);
+    }
+
+    /**
+     * Implement the Parcelable interface
+     * @hide
+     */
     public int describeContents() {
         return 0;
     }
 
+    /**
+     * Implement the Parcelable interface
+     * @hide
+     */
     public void writeToParcel(Parcel dest, int flags) {
         if (mDestination == null) {
             dest.writeByte((byte) 0);
@@ -208,38 +352,10 @@
         dest.writeString(mInterface);
     }
 
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-
-        if (!(obj instanceof RouteInfo)) return false;
-
-        RouteInfo target = (RouteInfo) obj;
-
-        boolean sameDestination = ( mDestination == null) ?
-                target.getDestination() == null
-                : mDestination.equals(target.getDestination());
-
-        boolean sameAddress = (mGateway == null) ?
-                target.getGateway() == null
-                : mGateway.equals(target.getGateway());
-
-        boolean sameInterface = (mInterface == null) ?
-                target.getInterface() == null
-                : mInterface.equals(target.getInterface());
-
-        return sameDestination && sameAddress && sameInterface
-            && mIsDefault == target.mIsDefault;
-    }
-
-    @Override
-    public int hashCode() {
-        return (mDestination == null ? 0 : mDestination.hashCode() * 41)
-            + (mGateway == null ? 0 :mGateway.hashCode() * 47)
-            + (mInterface == null ? 0 :mInterface.hashCode() * 67)
-            + (mIsDefault ? 3 : 7);
-    }
-
+    /**
+     * Implement the Parcelable interface.
+     * @hide
+     */
     public static final Creator<RouteInfo> CREATOR =
         new Creator<RouteInfo>() {
         public RouteInfo createFromParcel(Parcel in) {
@@ -279,39 +395,4 @@
             return new RouteInfo[size];
         }
     };
-
-    protected boolean matches(InetAddress destination) {
-        if (destination == null) return false;
-
-        // match the route destination and destination with prefix length
-        InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
-                mDestination.getNetworkPrefixLength());
-
-        return mDestination.getAddress().equals(dstNet);
-    }
-
-    /**
-     * Find the route from a Collection of routes that best matches a given address.
-     * May return null if no routes are applicable.
-     * @param routes a Collection of RouteInfos to chose from
-     * @param dest the InetAddress your trying to get to
-     * @return the RouteInfo from the Collection that best fits the given address
-     */
-    public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
-        if ((routes == null) || (dest == null)) return null;
-
-        RouteInfo bestRoute = null;
-        // pick a longest prefix match under same address type
-        for (RouteInfo route : routes) {
-            if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
-                if ((bestRoute != null) &&
-                        (bestRoute.mDestination.getNetworkPrefixLength() >=
-                        route.mDestination.getNetworkPrefixLength())) {
-                    continue;
-                }
-                if (route.matches(dest)) bestRoute = route;
-            }
-        }
-        return bestRoute;
-    }
 }
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index 5c8c8e9..ad940c6 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -621,8 +621,9 @@
      * Registers a listener.
      * 
      * @see OnActivityStopListener
+     * @hide
      */
-    void registerOnActivityStopListener(OnActivityStopListener listener) {
+    public void registerOnActivityStopListener(OnActivityStopListener listener) {
         synchronized (this) {
             if (mActivityStopListeners == null) {
                 mActivityStopListeners = new ArrayList<OnActivityStopListener>();
@@ -638,8 +639,9 @@
      * Unregisters a listener.
      * 
      * @see OnActivityStopListener
+     * @hide
      */
-    void unregisterOnActivityStopListener(OnActivityStopListener listener) {
+    public void unregisterOnActivityStopListener(OnActivityStopListener listener) {
         synchronized (this) {
             if (mActivityStopListeners != null) {
                 mActivityStopListeners.remove(listener);
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
new file mode 100644
index 0000000..d2d6ade
--- /dev/null
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -0,0 +1,248 @@
+/*
+ * 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.preference;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.preference.VolumePreference.VolumeStore;
+import android.provider.Settings;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+/**
+ * Turns a {@link SeekBar} into a volume control.
+ * @hide
+ */
+public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callback {
+
+    public interface Callback {
+        void onSampleStarting(SeekBarVolumizer sbv);
+    }
+
+    private Context mContext;
+    private Handler mHandler;
+    private final Callback mCallback;
+
+    private AudioManager mAudioManager;
+    private int mStreamType;
+    private int mOriginalStreamVolume;
+    private Ringtone mRingtone;
+
+    private int mLastProgress = -1;
+    private SeekBar mSeekBar;
+    private int mVolumeBeforeMute = -1;
+
+    private static final int MSG_SET_STREAM_VOLUME = 0;
+    private static final int MSG_START_SAMPLE = 1;
+    private static final int MSG_STOP_SAMPLE = 2;
+    private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000;
+
+    private ContentObserver mVolumeObserver = new ContentObserver(mHandler) {
+        @Override
+        public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            if (mSeekBar != null && mAudioManager != null) {
+                int volume = mAudioManager.getStreamVolume(mStreamType);
+                mSeekBar.setProgress(volume);
+            }
+        }
+    };
+
+    public SeekBarVolumizer(Context context, SeekBar seekBar, int streamType, Uri defaultUri,
+            Callback callback) {
+        mContext = context;
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        mStreamType = streamType;
+        mSeekBar = seekBar;
+
+        HandlerThread thread = new HandlerThread(VolumePreference.TAG + ".CallbackHandler");
+        thread.start();
+        mHandler = new Handler(thread.getLooper(), this);
+        mCallback = callback;
+
+        initSeekBar(seekBar, defaultUri);
+    }
+
+    private void initSeekBar(SeekBar seekBar, Uri defaultUri) {
+        seekBar.setMax(mAudioManager.getStreamMaxVolume(mStreamType));
+        mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType);
+        seekBar.setProgress(mOriginalStreamVolume);
+        seekBar.setOnSeekBarChangeListener(this);
+
+        mContext.getContentResolver().registerContentObserver(
+                System.getUriFor(System.VOLUME_SETTINGS[mStreamType]),
+                false, mVolumeObserver);
+
+        if (defaultUri == null) {
+            if (mStreamType == AudioManager.STREAM_RING) {
+                defaultUri = Settings.System.DEFAULT_RINGTONE_URI;
+            } else if (mStreamType == AudioManager.STREAM_NOTIFICATION) {
+                defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI;
+            } else {
+                defaultUri = Settings.System.DEFAULT_ALARM_ALERT_URI;
+            }
+        }
+
+        mRingtone = RingtoneManager.getRingtone(mContext, defaultUri);
+
+        if (mRingtone != null) {
+            mRingtone.setStreamType(mStreamType);
+        }
+    }
+
+    @Override
+    public boolean handleMessage(Message msg) {
+        switch (msg.what) {
+            case MSG_SET_STREAM_VOLUME:
+                mAudioManager.setStreamVolume(mStreamType, mLastProgress, 0);
+                break;
+            case MSG_START_SAMPLE:
+                onStartSample();
+                break;
+            case MSG_STOP_SAMPLE:
+                onStopSample();
+                break;
+            default:
+                Log.e(VolumePreference.TAG, "invalid SeekBarVolumizer message: "+msg.what);
+        }
+        return true;
+    }
+
+    private void postStartSample() {
+        mHandler.removeMessages(MSG_START_SAMPLE);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_SAMPLE),
+                isSamplePlaying() ? CHECK_RINGTONE_PLAYBACK_DELAY_MS : 0);
+    }
+
+    private void onStartSample() {
+        if (!isSamplePlaying()) {
+            if (mCallback != null) {
+                mCallback.onSampleStarting(this);
+            }
+            if (mRingtone != null) {
+                mRingtone.play();
+            }
+        }
+    }
+
+    void postStopSample() {
+        // remove pending delayed start messages
+        mHandler.removeMessages(MSG_START_SAMPLE);
+        mHandler.removeMessages(MSG_STOP_SAMPLE);
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_STOP_SAMPLE));
+    }
+
+    private void onStopSample() {
+        if (mRingtone != null) {
+            mRingtone.stop();
+        }
+    }
+
+    public void stop() {
+        postStopSample();
+        mContext.getContentResolver().unregisterContentObserver(mVolumeObserver);
+        mSeekBar.setOnSeekBarChangeListener(null);
+    }
+
+    public void revertVolume() {
+        mAudioManager.setStreamVolume(mStreamType, mOriginalStreamVolume, 0);
+    }
+
+    public void onProgressChanged(SeekBar seekBar, int progress,
+            boolean fromTouch) {
+        if (!fromTouch) {
+            return;
+        }
+
+        postSetVolume(progress);
+    }
+
+    void postSetVolume(int progress) {
+        // Do the volume changing separately to give responsive UI
+        mLastProgress = progress;
+        mHandler.removeMessages(MSG_SET_STREAM_VOLUME);
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_STREAM_VOLUME));
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+        postStartSample();
+    }
+
+    public boolean isSamplePlaying() {
+        return mRingtone != null && mRingtone.isPlaying();
+    }
+
+    public void startSample() {
+        postStartSample();
+    }
+
+    public void stopSample() {
+        postStopSample();
+    }
+
+    public SeekBar getSeekBar() {
+        return mSeekBar;
+    }
+
+    public void changeVolumeBy(int amount) {
+        mSeekBar.incrementProgressBy(amount);
+        postSetVolume(mSeekBar.getProgress());
+        postStartSample();
+        mVolumeBeforeMute = -1;
+    }
+
+    public void muteVolume() {
+        if (mVolumeBeforeMute != -1) {
+            mSeekBar.setProgress(mVolumeBeforeMute);
+            postSetVolume(mVolumeBeforeMute);
+            postStartSample();
+            mVolumeBeforeMute = -1;
+        } else {
+            mVolumeBeforeMute = mSeekBar.getProgress();
+            mSeekBar.setProgress(0);
+            postStopSample();
+            postSetVolume(0);
+        }
+    }
+
+    public void onSaveInstanceState(VolumeStore volumeStore) {
+        if (mLastProgress >= 0) {
+            volumeStore.volume = mLastProgress;
+            volumeStore.originalVolume = mOriginalStreamVolume;
+        }
+    }
+
+    public void onRestoreInstanceState(VolumeStore volumeStore) {
+        if (volumeStore.volume != -1) {
+            mOriginalStreamVolume = volumeStore.originalVolume;
+            mLastProgress = volumeStore.volume;
+            postSetVolume(mLastProgress);
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index 39cb826..171e5c3 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -19,32 +19,20 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.database.ContentObserver;
-import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.provider.Settings;
-import android.provider.Settings.System;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
 
 /**
  * @hide
  */
 public class VolumePreference extends SeekBarDialogPreference implements
-        PreferenceManager.OnActivityStopListener, View.OnKeyListener {
+        PreferenceManager.OnActivityStopListener, View.OnKeyListener, SeekBarVolumizer.Callback {
 
-    private static final String TAG = "VolumePreference";
+    static final String TAG = "VolumePreference";
 
     private int mStreamType;
 
@@ -78,7 +66,7 @@
         super.onBindDialogView(view);
 
         final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
-        mSeekBarVolumizer = new SeekBarVolumizer(getContext(), seekBar, mStreamType);
+        mSeekBarVolumizer = new SeekBarVolumizer(getContext(), seekBar, mStreamType, null, this);
 
         getPreferenceManager().registerOnActivityStopListener(this);
 
@@ -152,7 +140,8 @@
 
     }
 
-    protected void onSampleStarting(SeekBarVolumizer volumizer) {
+    @Override
+    public void onSampleStarting(SeekBarVolumizer volumizer) {
         if (mSeekBarVolumizer != null && volumizer != mSeekBarVolumizer) {
             mSeekBarVolumizer.stopSample();
         }
@@ -228,213 +217,4 @@
             }
         };
     }
-
-    /**
-     * Turns a {@link SeekBar} into a volume control.
-     */
-    public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callback {
-
-        private Context mContext;
-        private Handler mHandler;
-
-        private AudioManager mAudioManager;
-        private int mStreamType;
-        private int mOriginalStreamVolume;
-        private Ringtone mRingtone;
-
-        private int mLastProgress = -1;
-        private SeekBar mSeekBar;
-        private int mVolumeBeforeMute = -1;
-
-        private static final int MSG_SET_STREAM_VOLUME = 0;
-        private static final int MSG_START_SAMPLE = 1;
-        private static final int MSG_STOP_SAMPLE = 2;
-        private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000;
-
-        private ContentObserver mVolumeObserver = new ContentObserver(mHandler) {
-            @Override
-            public void onChange(boolean selfChange) {
-                super.onChange(selfChange);
-                if (mSeekBar != null && mAudioManager != null) {
-                    int volume = mAudioManager.getStreamVolume(mStreamType);
-                    mSeekBar.setProgress(volume);
-                }
-            }
-        };
-
-        public SeekBarVolumizer(Context context, SeekBar seekBar, int streamType) {
-            this(context, seekBar, streamType, null);
-        }
-
-        public SeekBarVolumizer(Context context, SeekBar seekBar, int streamType, Uri defaultUri) {
-            mContext = context;
-            mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-            mStreamType = streamType;
-            mSeekBar = seekBar;
-
-            HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler");
-            thread.start();
-            mHandler = new Handler(thread.getLooper(), this);
-
-            initSeekBar(seekBar, defaultUri);
-        }
-
-        private void initSeekBar(SeekBar seekBar, Uri defaultUri) {
-            seekBar.setMax(mAudioManager.getStreamMaxVolume(mStreamType));
-            mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType);
-            seekBar.setProgress(mOriginalStreamVolume);
-            seekBar.setOnSeekBarChangeListener(this);
-
-            mContext.getContentResolver().registerContentObserver(
-                    System.getUriFor(System.VOLUME_SETTINGS[mStreamType]),
-                    false, mVolumeObserver);
-
-            if (defaultUri == null) {
-                if (mStreamType == AudioManager.STREAM_RING) {
-                    defaultUri = Settings.System.DEFAULT_RINGTONE_URI;
-                } else if (mStreamType == AudioManager.STREAM_NOTIFICATION) {
-                    defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI;
-                } else {
-                    defaultUri = Settings.System.DEFAULT_ALARM_ALERT_URI;
-                }
-            }
-
-            mRingtone = RingtoneManager.getRingtone(mContext, defaultUri);
-
-            if (mRingtone != null) {
-                mRingtone.setStreamType(mStreamType);
-            }
-        }
-
-        @Override
-        public boolean handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_SET_STREAM_VOLUME:
-                    mAudioManager.setStreamVolume(mStreamType, mLastProgress, 0);
-                    break;
-                case MSG_START_SAMPLE:
-                    onStartSample();
-                    break;
-                case MSG_STOP_SAMPLE:
-                    onStopSample();
-                    break;
-                default:
-                    Log.e(TAG, "invalid SeekBarVolumizer message: "+msg.what);
-            }
-            return true;
-        }
-
-        private void postStartSample() {
-            mHandler.removeMessages(MSG_START_SAMPLE);
-            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_SAMPLE),
-                    isSamplePlaying() ? CHECK_RINGTONE_PLAYBACK_DELAY_MS : 0);
-        }
-
-        private void onStartSample() {
-            if (!isSamplePlaying()) {
-                onSampleStarting(this);
-                if (mRingtone != null) {
-                    mRingtone.play();
-                }
-            }
-        }
-
-        private void postStopSample() {
-            // remove pending delayed start messages
-            mHandler.removeMessages(MSG_START_SAMPLE);
-            mHandler.removeMessages(MSG_STOP_SAMPLE);
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_STOP_SAMPLE));
-        }
-
-        private void onStopSample() {
-            if (mRingtone != null) {
-                mRingtone.stop();
-            }
-        }
-
-        public void stop() {
-            postStopSample();
-            mContext.getContentResolver().unregisterContentObserver(mVolumeObserver);
-            mSeekBar.setOnSeekBarChangeListener(null);
-        }
-
-        public void revertVolume() {
-            mAudioManager.setStreamVolume(mStreamType, mOriginalStreamVolume, 0);
-        }
-
-        public void onProgressChanged(SeekBar seekBar, int progress,
-                boolean fromTouch) {
-            if (!fromTouch) {
-                return;
-            }
-
-            postSetVolume(progress);
-        }
-
-        void postSetVolume(int progress) {
-            // Do the volume changing separately to give responsive UI
-            mLastProgress = progress;
-            mHandler.removeMessages(MSG_SET_STREAM_VOLUME);
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_STREAM_VOLUME));
-        }
-
-        public void onStartTrackingTouch(SeekBar seekBar) {
-        }
-
-        public void onStopTrackingTouch(SeekBar seekBar) {
-            postStartSample();
-        }
-
-        public boolean isSamplePlaying() {
-            return mRingtone != null && mRingtone.isPlaying();
-        }
-
-        public void startSample() {
-            postStartSample();
-        }
-
-        public void stopSample() {
-            postStopSample();
-        }
-
-        public SeekBar getSeekBar() {
-            return mSeekBar;
-        }
-
-        public void changeVolumeBy(int amount) {
-            mSeekBar.incrementProgressBy(amount);
-            postSetVolume(mSeekBar.getProgress());
-            postStartSample();
-            mVolumeBeforeMute = -1;
-        }
-
-        public void muteVolume() {
-            if (mVolumeBeforeMute != -1) {
-                mSeekBar.setProgress(mVolumeBeforeMute);
-                postSetVolume(mVolumeBeforeMute);
-                postStartSample();
-                mVolumeBeforeMute = -1;
-            } else {
-                mVolumeBeforeMute = mSeekBar.getProgress();
-                mSeekBar.setProgress(0);
-                postStopSample();
-                postSetVolume(0);
-            }
-        }
-
-        public void onSaveInstanceState(VolumeStore volumeStore) {
-            if (mLastProgress >= 0) {
-                volumeStore.volume = mLastProgress;
-                volumeStore.originalVolume = mOriginalStreamVolume;
-            }
-        }
-
-        public void onRestoreInstanceState(VolumeStore volumeStore) {
-            if (volumeStore.volume != -1) {
-                mOriginalStreamVolume = volumeStore.originalVolume;
-                mLastProgress = volumeStore.volume;
-                postSetVolume(mLastProgress);
-            }
-        }
-    }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cd28085..e896063 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4556,6 +4556,12 @@
         public static final String PAYMENT_SERVICE_SEARCH_URI = "payment_service_search_uri";
 
         /**
+         * If enabled, intercepted notifications will be displayed (not suppressed) in zen mode.
+         * @hide
+         */
+        public static final String DISPLAY_INTERCEPTED_NOTIFICATIONS = "display_intercepted_notifications";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
diff --git a/core/java/android/speech/tts/TextToSpeechClient.java b/core/java/android/speech/tts/TextToSpeechClient.java
index 10e2073..85f702b 100644
--- a/core/java/android/speech/tts/TextToSpeechClient.java
+++ b/core/java/android/speech/tts/TextToSpeechClient.java
@@ -25,7 +25,10 @@
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.speech.tts.ITextToSpeechCallback;
@@ -86,6 +89,8 @@
     private HashMap<String, Pair<UtteranceId, RequestCallbacks>> mCallbacks;
     // Guarded by mLock
 
+    private InternalHandler mMainHandler = new InternalHandler();
+
     /** Common voices parameters */
     public static final class Params {
         private Params() {}
@@ -300,6 +305,8 @@
     /**
      * Interface definition of callbacks that are called when the client is
      * connected or disconnected from the TTS service.
+     *
+     * The callbacks specified in this method will be called on the UI thread.
      */
     public static interface ConnectionCallbacks {
         /**
@@ -325,6 +332,9 @@
          * with the speech service (e.g. a crash or resource problem causes it to be killed by the
          * system). When called, all requests have been canceled and no outstanding listeners will
          * be executed. Applications should disable UI components that require the service.
+         *
+         * When the service is working again, the client will receive a callback to the
+         * {@link #onConnectionSuccess()} method.
          */
         public void onServiceDisconnected();
 
@@ -688,7 +698,8 @@
                 synchronized (mLock) {
                     mEngineStatus = new EngineStatus(mServiceConnection.getEngineName(),
                             voicesInfo);
-                    mConnectionCallbacks.onEngineStatusChange(mEngineStatus);
+                    mMainHandler.obtainMessage(InternalHandler.WHAT_ENGINE_STATUS_CHANGED,
+                            mEngineStatus).sendToTarget();
                 }
             }
         };
@@ -753,9 +764,11 @@
             Log.i(TAG, "Asked to disconnect from " + name);
 
             synchronized(mLock) {
+                mEstablished = false;
+                mService = null;
                 stopSetupConnectionTask();
             }
-            mConnectionCallbacks.onServiceDisconnected();
+            mMainHandler.obtainMessage(InternalHandler.WHAT_SERVICE_DISCONNECTED).sendToTarget();
         }
 
         private void startSetupConnectionTask(ComponentName name) {
@@ -830,9 +843,11 @@
     private boolean runAction(Action action) {
         synchronized (mLock) {
             if (mServiceConnection == null) {
+                Log.w(TAG, action.getName() + " failed: not bound to TTS engine");
                 return false;
             }
             if (!mServiceConnection.isEstablished()) {
+                Log.w(TAG, action.getName() + " failed: not fully bound to TTS engine");
                 return false;
             }
             mServiceConnection.runAction(action);
@@ -1044,4 +1059,21 @@
             }
         });
     }
+
+    class InternalHandler extends Handler {
+        final static int WHAT_ENGINE_STATUS_CHANGED = 1;
+        final static int WHAT_SERVICE_DISCONNECTED = 2;
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case WHAT_ENGINE_STATUS_CHANGED:
+                    mConnectionCallbacks.onEngineStatusChange((EngineStatus) msg.obj);
+                    return;
+                case WHAT_SERVICE_DISCONNECTED:
+                    mConnectionCallbacks.onServiceDisconnected();
+                    return;
+            }
+        }
+    }
 }
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index d7c51fc..6b899d9 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -255,7 +255,8 @@
         // V2 to V1 interface adapter. This allows using V2 client interface on V1-only services.
         Bundle defaultParams = new Bundle();
         defaultParams.putFloat(TextToSpeechClient.Params.SPEECH_PITCH, 1.0f);
-        defaultParams.putFloat(TextToSpeechClient.Params.SPEECH_SPEED, -1.0f);
+        // Speech speed <= 0 makes it use a system wide setting
+        defaultParams.putFloat(TextToSpeechClient.Params.SPEECH_SPEED, 0.0f);
 
         // Enumerate all locales and check if they are available
         ArrayList<VoiceInfo> voicesInfo = new ArrayList<VoiceInfo>();
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 17035b1..74972c2 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -193,7 +193,7 @@
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
         HardwareCanvas canvas = mRootNode.start(mWidth, mHeight);
         try {
-            callbacks.onHardwarePostDraw(canvas);
+            callbacks.onHardwarePreDraw(canvas);
             canvas.drawDisplayList(view.getDisplayList());
             callbacks.onHardwarePostDraw(canvas);
         } finally {
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index ac12357..aaf0a75 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -30,6 +30,9 @@
     private static final String CHROMIUM_WEBVIEW_FACTORY =
             "com.android.webview.chromium.WebViewChromiumFactoryProvider";
 
+    private static final String NULL_WEBVIEW_FACTORY =
+            "com.android.webview.nullwebview.NullWebViewFactoryProvider";
+
     private static final String LOGTAG = "WebViewFactory";
 
     private static final boolean DEBUG = false;
@@ -88,6 +91,11 @@
     }
 
     private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException {
-        return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY);
+        try {
+            return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY);
+        } catch (ClassNotFoundException e) {
+            Log.e(LOGTAG, "Chromium WebView does not exist");
+            return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
+        }
     }
 }
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 79a8f44..a238ae3 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -183,7 +183,7 @@
 
     private void init(View decor) {
         mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
-                com.android.internal.R.id.action_bar_overlay_layout);
+                com.android.internal.R.id.decor_content_parent);
         if (mOverlayLayout != null) {
             mOverlayLayout.setActionBarVisibilityCallback(this);
         }
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 75feb5d..8fa662d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -36,9 +36,12 @@
     void setImeWindowStatus(in IBinder token, int vis, int backDisposition,
             boolean showImeSwitcher);
     void setHardKeyboardStatus(boolean available, boolean enabled);
+    void setWindowState(int window, int state);
+
+    void showRecentApps(boolean triggeredFromAltTab);
+    void hideRecentApps();
     void toggleRecentApps();
     void preloadRecentApps();
     void cancelPreloadRecentApps();
-    void setWindowState(int window, int state);
 }
 
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index cf334c3..9ebfd78 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -52,8 +52,11 @@
             in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys);
     void setSystemUiVisibility(int vis, int mask);
     void setHardKeyboardEnabled(boolean enabled);
+    void setWindowState(int window, int state);
+
+    void showRecentApps(boolean triggeredFromAltTab);
+    void hideRecentApps();
     void toggleRecentApps();
     void preloadRecentApps();
     void cancelPreloadRecentApps();
-    void setWindowState(int window, int state);
 }
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 4b84941..81e67d8 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -48,6 +48,8 @@
     public static final int BASE_WIFI_CONTROLLER                                    = 0x00026000;
     public static final int BASE_WIFI_SCANNER                                       = 0x00027000;
     public static final int BASE_WIFI_SCANNER_SERVICE                               = 0x00027100;
+    public static final int BASE_WIFI_PASSPOINT_MANAGER                             = 0x00028000;
+    public static final int BASE_WIFI_PASSPOINT_SERVICE                             = 0x00028100;
     public static final int BASE_DHCP                                               = 0x00030000;
     public static final int BASE_DATA_CONNECTION                                    = 0x00040000;
     public static final int BASE_DATA_CONNECTION_AC                                 = 0x00041000;
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 19d58bf..7ab4bed 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -19,26 +19,34 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.util.IntProperty;
+import android.util.Log;
 import android.util.Property;
+import android.util.SparseArray;
+import android.view.KeyEvent;
+import android.view.Menu;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewPropertyAnimator;
+import android.view.Window;
 import android.view.WindowInsets;
 import android.widget.OverScroller;
+import com.android.internal.view.menu.MenuPresenter;
 
 /**
  * Special layout for the containing of an overlay action bar (and its
  * content) to correctly handle fitting system windows when the content
  * has request that its layout ignore them.
  */
-public class ActionBarOverlayLayout extends ViewGroup {
+public class ActionBarOverlayLayout extends ViewGroup implements DecorContentParent {
     private static final String TAG = "ActionBarOverlayLayout";
 
     private int mActionBarHeight;
@@ -47,7 +55,7 @@
 
     // The main UI elements that we handle the layout of.
     private View mContent;
-    private View mActionBarBottom;
+    private ActionBarContainer mActionBarBottom;
     private ActionBarContainer mActionBarTop;
 
     // Some interior UI elements.
@@ -556,7 +564,8 @@
             mActionBarTop = (ActionBarContainer) findViewById(
                     com.android.internal.R.id.action_bar_container);
             mActionBarView = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
-            mActionBarBottom = findViewById(com.android.internal.R.id.split_action_bar);
+            mActionBarBottom = (ActionBarContainer) findViewById(
+                    com.android.internal.R.id.split_action_bar);
         }
     }
 
@@ -629,6 +638,179 @@
         return finalY > mActionBarTop.getHeight();
     }
 
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (super.dispatchKeyEvent(event)) {
+            return true;
+        }
+
+        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+            final int action = event.getAction();
+
+            // Collapse any expanded action views.
+            if (mActionBarView != null && mActionBarView.hasExpandedActionView()) {
+                if (action == KeyEvent.ACTION_UP) {
+                    mActionBarView.collapseActionView();
+                }
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public void setWindowCallback(Window.Callback cb) {
+        pullChildren();
+        mActionBarView.setWindowCallback(cb);
+    }
+
+    @Override
+    public void setWindowTitle(CharSequence title) {
+        pullChildren();
+        mActionBarView.setWindowTitle(title);
+    }
+
+    @Override
+    public CharSequence getTitle() {
+        pullChildren();
+        return mActionBarView.getTitle();
+    }
+
+    @Override
+    public void initFeature(int windowFeature) {
+        pullChildren();
+        switch (windowFeature) {
+            case Window.FEATURE_PROGRESS:
+                mActionBarView.initProgress();
+                break;
+            case Window.FEATURE_INDETERMINATE_PROGRESS:
+                mActionBarView.initIndeterminateProgress();
+                break;
+            case Window.FEATURE_ACTION_BAR_OVERLAY:
+                setOverlayMode(true);
+                break;
+        }
+    }
+
+    @Override
+    public void setUiOptions(int uiOptions) {
+        boolean splitActionBar = false;
+        final boolean splitWhenNarrow =
+                (uiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0;
+        if (splitWhenNarrow) {
+            splitActionBar = getContext().getResources().getBoolean(
+                    com.android.internal.R.bool.split_action_bar_is_narrow);
+        }
+        if (splitActionBar) {
+            pullChildren();
+            if (mActionBarBottom != null) {
+                mActionBarView.setSplitView(mActionBarBottom);
+                mActionBarView.setSplitActionBar(splitActionBar);
+                mActionBarView.setSplitWhenNarrow(splitWhenNarrow);
+
+                final ActionBarContextView cab = (ActionBarContextView) findViewById(
+                        com.android.internal.R.id.action_context_bar);
+                cab.setSplitView(mActionBarBottom);
+                cab.setSplitActionBar(splitActionBar);
+                cab.setSplitWhenNarrow(splitWhenNarrow);
+            } else if (splitActionBar) {
+                Log.e(TAG, "Requested split action bar with " +
+                        "incompatible window decor! Ignoring request.");
+            }
+        }
+    }
+
+    @Override
+    public boolean hasIcon() {
+        pullChildren();
+        return mActionBarView.hasIcon();
+    }
+
+    @Override
+    public boolean hasLogo() {
+        pullChildren();
+        return mActionBarView.hasLogo();
+    }
+
+    @Override
+    public void setIcon(int resId) {
+        pullChildren();
+        mActionBarView.setIcon(resId);
+    }
+
+    @Override
+    public void setIcon(Drawable d) {
+        pullChildren();
+        mActionBarView.setIcon(d);
+    }
+
+    @Override
+    public void setLogo(int resId) {
+        pullChildren();
+        mActionBarView.setLogo(resId);
+    }
+
+    @Override
+    public boolean canShowOverflowMenu() {
+        pullChildren();
+        return mActionBarView.isOverflowReserved() && mActionBarView.getVisibility() == VISIBLE;
+    }
+
+    @Override
+    public boolean isOverflowMenuShowing() {
+        pullChildren();
+        return mActionBarView.isOverflowMenuShowing();
+    }
+
+    @Override
+    public boolean isOverflowMenuShowPending() {
+        pullChildren();
+        return mActionBarView.isOverflowMenuShowPending();
+    }
+
+    @Override
+    public boolean showOverflowMenu() {
+        pullChildren();
+        return mActionBarView.showOverflowMenu();
+    }
+
+    @Override
+    public boolean hideOverflowMenu() {
+        pullChildren();
+        return mActionBarView.hideOverflowMenu();
+    }
+
+    @Override
+    public void setMenuPrepared() {
+        pullChildren();
+        mActionBarView.setMenuPrepared();
+    }
+
+    @Override
+    public void setMenu(Menu menu, MenuPresenter.Callback cb) {
+        pullChildren();
+        mActionBarView.setMenu(menu, cb);
+    }
+
+    @Override
+    public void saveToolbarHierarchyState(SparseArray<Parcelable> toolbarStates) {
+        pullChildren();
+        mActionBarView.saveHierarchyState(toolbarStates);
+    }
+
+    @Override
+    public void restoreToolbarHierarchyState(SparseArray<Parcelable> toolbarStates) {
+        pullChildren();
+        mActionBarView.restoreHierarchyState(toolbarStates);
+    }
+
+    @Override
+    public void dismissPopups() {
+        pullChildren();
+        mActionBarView.dismissPopupMenus();
+    }
+
     public static class LayoutParams extends MarginLayoutParams {
         public LayoutParams(Context c, AttributeSet attrs) {
             super(c, attrs);
diff --git a/core/java/com/android/internal/widget/DecorContentParent.java b/core/java/com/android/internal/widget/DecorContentParent.java
new file mode 100644
index 0000000..4fa370a
--- /dev/null
+++ b/core/java/com/android/internal/widget/DecorContentParent.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.widget;
+
+import android.graphics.drawable.Drawable;
+import android.os.Parcelable;
+import android.util.SparseArray;
+import android.view.Menu;
+import android.view.Window;
+import com.android.internal.view.menu.MenuPresenter;
+
+/**
+ * Implemented by the top-level decor layout for a window. DecorContentParent offers
+ * entry points for a number of title/window decor features.
+ */
+public interface DecorContentParent {
+    void setWindowCallback(Window.Callback cb);
+    void setWindowTitle(CharSequence title);
+    CharSequence getTitle();
+    void initFeature(int windowFeature);
+    void setUiOptions(int uiOptions);
+    boolean hasIcon();
+    boolean hasLogo();
+    void setIcon(int resId);
+    void setIcon(Drawable d);
+    void setLogo(int resId);
+    boolean canShowOverflowMenu();
+    boolean isOverflowMenuShowing();
+    boolean isOverflowMenuShowPending();
+    boolean showOverflowMenu();
+    boolean hideOverflowMenu();
+    void setMenuPrepared();
+    void setMenu(Menu menu, MenuPresenter.Callback cb);
+    void saveToolbarHierarchyState(SparseArray<Parcelable> toolbarStates);
+    void restoreToolbarHierarchyState(SparseArray<Parcelable> toolbarStates);
+    void dismissPopups();
+
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 0ad2ab2..99bbe39 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -228,6 +228,7 @@
 	libz \
 	libaudioutils \
 	libpdfrenderer \
+	libimg_utils \
 
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index fa2cfe3..3312109 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -30,6 +30,7 @@
 #include "JNIHelp.h"
 #include "android_os_Parcel.h"
 #include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
 
 #include <binder/IServiceManager.h>
 #include <camera/CameraMetadata.h>
@@ -57,6 +58,31 @@
 
 static fields_t fields;
 
+namespace android {
+
+status_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz,
+        /*out*/CameraMetadata* metadata) {
+    if (!thiz) {
+        ALOGE("%s: Invalid java metadata object.", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    if (!metadata) {
+        ALOGE("%s: Invalid output metadata object.", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    CameraMetadata* nativePtr = reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz,
+            fields.metadata_ptr));
+    if (nativePtr == NULL) {
+        ALOGE("%s: Invalid native pointer in java metadata object.", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    *metadata = *nativePtr;
+    return OK;
+}
+
+} /*namespace android*/
+
 namespace {
 struct Helpers {
     static size_t getTypeSize(uint8_t type) {
diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml
deleted file mode 100644
index 02c99fe..0000000
--- a/core/res/res/layout-xlarge/screen_action_bar.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!--
-This is an optimized layout for a screen with
-the Action Bar enabled overlaying application content.
--->
-
-<com.android.internal.widget.ActionBarOverlayLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/action_bar_overlay_layout"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:splitMotionEvents="false">
-    <FrameLayout android:id="@android:id/content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-    <com.android.internal.widget.ActionBarContainer
-        android:id="@+id/action_bar_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentTop="true"
-        style="?android:attr/actionBarStyle"
-        android:viewName="android:action_bar"
-        android:gravity="top">
-        <com.android.internal.widget.ActionBarView
-            android:id="@+id/action_bar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            style="?android:attr/actionBarStyle" />
-        <com.android.internal.widget.ActionBarContextView
-            android:id="@+id/action_context_bar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-            style="?android:attr/actionModeStyle" />
-    </com.android.internal.widget.ActionBarContainer>
-</com.android.internal.widget.ActionBarOverlayLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index eb237b3..8bf8416 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -20,7 +20,7 @@
 
 <com.android.internal.widget.ActionBarOverlayLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/action_bar_overlay_layout"
+    android:id="@+id/decor_content_parent"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:splitMotionEvents="false"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3746780..9fba1bf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -355,10 +355,6 @@
              when there is not reserved space for their UI (such as an Action Bar). -->
         <attr name="windowActionModeOverlay" format="boolean" />
 
-        <!-- Flag indicating that the action bar should be split to provide more
-             room for elements. -->
-        <attr name="windowSplitActionBar" format="boolean" />
-
         <!-- Defines the default soft input state that this window would
              like when it is displayed.  Corresponds
              to {@link android.view.WindowManager.LayoutParams#softInputMode}. -->
@@ -1705,7 +1701,6 @@
         <attr name="windowActionBar" />
         <attr name="windowActionModeOverlay" />
         <attr name="windowActionBarOverlay" />
-        <attr name="windowSplitActionBar" />
         <attr name="windowEnableSplitTouch" />
         <attr name="windowCloseOnTouchOutside" />
         <attr name="windowTranslucentStatus" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2f0ac49..2d60b86 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -31,7 +31,6 @@
   <java-symbol type="id" name="account_type" />
   <java-symbol type="id" name="action_bar" />
   <java-symbol type="id" name="action_bar_container" />
-  <java-symbol type="id" name="action_bar_overlay_layout" />
   <java-symbol type="id" name="action_bar_title" />
   <java-symbol type="id" name="action_bar_subtitle" />
   <java-symbol type="id" name="action_context_bar" />
@@ -61,6 +60,7 @@
   <java-symbol type="id" name="day" />
   <java-symbol type="id" name="day_names" />
   <java-symbol type="id" name="decrement" />
+  <java-symbol type="id" name="decor_content_parent" />
   <java-symbol type="id" name="default_activity_button" />
   <java-symbol type="id" name="deny_button" />
   <java-symbol type="id" name="description" />
diff --git a/include/android_runtime/android_hardware_camera2_CameraMetadata.h b/include/android_runtime/android_hardware_camera2_CameraMetadata.h
new file mode 100644
index 0000000..3c76ca5
--- /dev/null
+++ b/include/android_runtime/android_hardware_camera2_CameraMetadata.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA2_CAMERAMETADATA_JNI_H
+#define ANDROID_HARDWARE_CAMERA2_CAMERAMETADATA_JNI_H
+
+#include <camera/CameraMetadata.h>
+
+#include "jni.h"
+
+namespace android {
+
+/**
+ * Copies the native metadata for this java object into the given output CameraMetadata object.
+ */
+status_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz,
+               /*out*/CameraMetadata* metadata);
+
+} /*namespace android*/
+
+#endif /*ANDROID_HARDWARE_CAMERA2_CAMERAMETADATA_JNI_H*/
diff --git a/media/java/android/media/DngCreator.java b/media/java/android/media/DngCreator.java
index b2a38ab..76c6d46 100644
--- a/media/java/android/media/DngCreator.java
+++ b/media/java/android/media/DngCreator.java
@@ -17,9 +17,12 @@
 package android.media;
 
 import android.graphics.Bitmap;
+import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.impl.CameraMetadataNative;
 import android.location.Location;
+import android.util.Size;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -50,7 +53,7 @@
  * Adobe DNG 1.4.0.0 specification</a>.
  * </p>
  */
-public final class DngCreator {
+public final class DngCreator implements AutoCloseable {
 
     /**
      * Create a new DNG object.
@@ -68,7 +71,12 @@
      *          {@link android.hardware.camera2.CameraCharacteristics}.
      * @param metadata a metadata object to generate tags from.
      */
-    public DngCreator(CameraCharacteristics characteristics, CaptureResult metadata) {/*TODO*/}
+    public DngCreator(CameraCharacteristics characteristics, CaptureResult metadata) {
+        if (characteristics == null || metadata == null) {
+            throw new NullPointerException("Null argument to DngCreator constructor");
+        }
+        nativeInit(characteristics.getNativeCopy(), metadata.getNativeCopy());
+    }
 
     /**
      * Set the orientation value to write.
@@ -92,6 +100,13 @@
      * @return this {@link #DngCreator} object.
      */
     public DngCreator setOrientation(int orientation) {
+
+        if (orientation < ExifInterface.ORIENTATION_UNDEFINED ||
+                orientation > ExifInterface.ORIENTATION_ROTATE_270) {
+            throw new IllegalArgumentException("Orientation " + orientation +
+                    " is not a valid EXIF orientation value");
+        }
+        nativeSetOrientation(orientation);
         return this;
     }
 
@@ -111,6 +126,20 @@
      * @return this {@link #DngCreator} object.
      */
     public DngCreator setThumbnail(Bitmap pixels) {
+        if (pixels == null) {
+            throw new NullPointerException("Null argument to setThumbnail");
+        }
+
+        Bitmap.Config config = pixels.getConfig();
+
+        if (config != Bitmap.Config.ARGB_8888) {
+            pixels = pixels.copy(Bitmap.Config.ARGB_8888, false);
+            if (pixels == null) {
+                throw new IllegalArgumentException("Unsupported Bitmap format " + config);
+            }
+            nativeSetThumbnailBitmap(pixels);
+        }
+
         return this;
     }
 
@@ -130,6 +159,21 @@
      * @return this {@link #DngCreator} object.
      */
     public DngCreator setThumbnail(Image pixels) {
+        if (pixels == null) {
+            throw new NullPointerException("Null argument to setThumbnail");
+        }
+
+        int format = pixels.getFormat();
+        if (format != ImageFormat.YUV_420_888) {
+            throw new IllegalArgumentException("Unsupported image format " + format);
+        }
+
+        Image.Plane[] planes = pixels.getPlanes();
+        nativeSetThumbnailImage(pixels.getWidth(), pixels.getHeight(), planes[0].getBuffer(),
+                planes[0].getRowStride(), planes[0].getPixelStride(), planes[1].getBuffer(),
+                planes[1].getRowStride(), planes[1].getPixelStride(), planes[1].getBuffer(),
+                planes[1].getRowStride(), planes[1].getPixelStride());
+
         return this;
     }
 
@@ -150,7 +194,10 @@
      * @throws java.lang.IllegalArgumentException if the given location object doesn't
      *          contain enough information to set location metadata.
      */
-    public DngCreator setLocation(Location location) { return this; }
+    public DngCreator setLocation(Location location) {
+        /*TODO*/
+        return this;
+    }
 
     /**
      * Set the user description string to write.
@@ -163,6 +210,7 @@
      * @return this {@link #DngCreator} object.
      */
     public DngCreator setDescription(String description) {
+        /*TODO*/
         return this;
     }
 
@@ -172,32 +220,33 @@
      *
      * <p>
      * Raw pixel data must have 16 bits per pixel, and the input must contain at least
-     * {@code offset + 2 * (stride * (height - 1) + width * height)} bytes.  The width and height of
+     * {@code offset + 2 * width * height)} bytes.  The width and height of
      * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
      * and will typically be equal to the width and height of
-     * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
-     * If insufficient metadata is set to write a well-formatted DNG file, and
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
+     * The pixel layout in the input is determined from the reported color filter arrangement (CFA)
+     * set in {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}.  If insufficient
+     * metadata is available to write a well-formatted DNG file, an
      * {@link java.lang.IllegalStateException} will be thrown.
      * </p>
      *
-     * <p>
-     * When reading from the pixel input, {@code stride} pixels will be skipped
-     * after each row (excluding the last).
-     * </p>
-     *
      * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
+     * @param size the {@link Size} of the image to write, in pixels.
      * @param pixels an {@link java.io.InputStream} of pixel data to write.
-     * @param stride the stride of the raw image in pixels.
      * @param offset the offset of the raw image in bytes.  This indicates how many bytes will
      *               be skipped in the input before any pixel data is read.
      *
      * @throws IOException if an error was encountered in the input or output stream.
      * @throws java.lang.IllegalStateException if not enough metadata information has been
      *          set to write a well-formatted DNG file.
+     * @throws java.lang.IllegalArgumentException if the size passed in does not match the
      */
-    public void writeInputStream(OutputStream dngOutput, InputStream pixels, int stride,
-                                 long offset) throws IOException {
-        /*TODO*/
+    public void writeInputStream(OutputStream dngOutput, Size size, InputStream pixels, long offset)
+            throws IOException {
+        if (dngOutput == null || pixels == null) {
+            throw new NullPointerException("Null argument to writeImage");
+        }
+        nativeWriteInputStream(dngOutput, pixels, offset);
     }
 
     /**
@@ -206,22 +255,18 @@
      *
      * <p>
      * Raw pixel data must have 16 bits per pixel, and the input must contain at least
-     * {@code offset + 2 * (stride * (height - 1) + width * height)} bytes.  The width and height of
+     * {@code offset + 2 * width * height)} bytes.  The width and height of
      * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
      * and will typically be equal to the width and height of
-     * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
-     * If insufficient metadata is set to write a well-formatted DNG file, and
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
+     * The pixel layout in the input is determined from the reported color filter arrangement (CFA)
+     * set in {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}.  If insufficient
+     * metadata is available to write a well-formatted DNG file, an
      * {@link java.lang.IllegalStateException} will be thrown.
      * </p>
      *
-     * <p>
-     * When reading from the pixel input, {@code stride} pixels will be skipped
-     * after each row (excluding the last).
-     * </p>
-     *
      * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
      * @param pixels an {@link java.nio.ByteBuffer} of pixel data to write.
-     * @param stride the stride of the raw image in pixels.
      * @param offset the offset of the raw image in bytes.  This indicates how many bytes will
      *               be skipped in the input before any pixel data is read.
      *
@@ -229,8 +274,13 @@
      * @throws java.lang.IllegalStateException if not enough metadata information has been
      *          set to write a well-formatted DNG file.
      */
-    public void writeByteBuffer(OutputStream dngOutput, ByteBuffer pixels, int stride,
-                                long offset) throws IOException {/*TODO*/}
+    public void writeByteBuffer(OutputStream dngOutput, Size size, ByteBuffer pixels, long offset)
+            throws IOException {
+        if (dngOutput == null || pixels == null) {
+            throw new NullPointerException("Null argument to writeImage");
+        }
+        nativeWriteByteBuffer(dngOutput, pixels, offset);
+    }
 
     /**
      * Write the pixel data to a DNG file with the currently configured metadata.
@@ -249,6 +299,70 @@
      * @throws java.lang.IllegalStateException if not enough metadata information has been
      *          set to write a well-formatted DNG file.
      */
-    public void writeImage(OutputStream dngOutput, Image pixels) throws IOException {/*TODO*/}
+    public void writeImage(OutputStream dngOutput, Image pixels) throws IOException {
+        if (dngOutput == null || pixels == null) {
+            throw new NullPointerException("Null argument to writeImage");
+        }
 
+        int format = pixels.getFormat();
+        if (format != ImageFormat.RAW_SENSOR) {
+            throw new IllegalArgumentException("Unsupported image format " + format);
+        }
+
+        Image.Plane[] planes = pixels.getPlanes();
+        nativeWriteImage(dngOutput, pixels.getWidth(), pixels.getHeight(), planes[0].getBuffer(),
+                planes[0].getRowStride(), planes[0].getPixelStride());
+    }
+
+    @Override
+    public void close() {
+        nativeDestroy();
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * This field is used by native code, do not access or modify.
+     */
+    private long mNativeContext;
+
+    private static native void nativeClassInit();
+
+    private synchronized native void nativeInit(CameraMetadataNative nativeCharacteristics,
+                                                CameraMetadataNative nativeResult);
+
+    private synchronized native void nativeDestroy();
+
+    private synchronized native void nativeSetOrientation(int orientation);
+
+    private synchronized native void nativeSetThumbnailBitmap(Bitmap bitmap);
+
+    private synchronized native void nativeSetThumbnailImage(int width, int height,
+                                                             ByteBuffer yBuffer, int yRowStride,
+                                                             int yPixStride, ByteBuffer uBuffer,
+                                                             int uRowStride, int uPixStride,
+                                                             ByteBuffer vBuffer, int vRowStride,
+                                                             int vPixStride);
+
+    private synchronized native void nativeWriteImage(OutputStream out, int width, int height,
+                                                      ByteBuffer rawBuffer, int rowStride,
+                                                      int pixStride) throws IOException;
+
+    private synchronized native void nativeWriteByteBuffer(OutputStream out, ByteBuffer rawBuffer,
+                                                           long offset) throws IOException;
+
+    private synchronized native void nativeWriteInputStream(OutputStream out, InputStream rawStream,
+                                                            long offset) throws IOException;
+
+    static {
+        System.loadLibrary("media_jni");
+        nativeClassInit();
+    }
 }
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 90fe695..d658654 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
+    android_media_DngCreator.cpp \
     android_media_ImageReader.cpp \
     android_media_MediaCrypto.cpp \
     android_media_MediaCodec.cpp \
@@ -41,6 +42,7 @@
     libjhead \
     libexif \
     libstagefright_amrnb_common \
+    libimg_utils \
 
 LOCAL_REQUIRED_MODULES := \
     libjhead_jni
@@ -53,6 +55,7 @@
     external/tremor/Tremor \
     frameworks/base/core/jni \
     frameworks/av/media/libmedia \
+    frameworks/av/media/img_utils/include \
     frameworks/av/media/libstagefright \
     frameworks/av/media/libstagefright/codecs/amrnb/enc/src \
     frameworks/av/media/libstagefright/codecs/amrnb/common \
diff --git a/media/jni/android_media_DngCreator.cpp b/media/jni/android_media_DngCreator.cpp
new file mode 100644
index 0000000..860d896
--- /dev/null
+++ b/media/jni/android_media_DngCreator.cpp
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "DngCreator_JNI"
+
+#include <system/camera_metadata.h>
+#include <camera/CameraMetadata.h>
+#include <img_utils/DngUtils.h>
+#include <img_utils/TagDefinitions.h>
+#include <img_utils/TiffIfd.h>
+#include <img_utils/TiffWriter.h>
+#include <img_utils/Output.h>
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/RefBase.h>
+#include <cutils/properties.h>
+
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+using namespace android;
+using namespace img_utils;
+
+#define BAIL_IF_INVALID(expr, jnienv, tagId) \
+    if ((expr) != OK) { \
+        jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
+                "Invalid metadata for tag %x", tagId); \
+        return; \
+    }
+
+#define BAIL_IF_EMPTY(entry, jnienv, tagId) \
+    if (entry.count == 0) { \
+        jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
+                "Missing metadata fields for tag %x", tagId); \
+        return; \
+    }
+
+#define ANDROID_MEDIA_DNGCREATOR_CTX_JNI_ID     "mNativeContext"
+
+static struct {
+    jfieldID mNativeContext;
+} gDngCreatorClassInfo;
+
+static struct {
+    jmethodID mWriteMethod;
+} gOutputStreamClassInfo;
+
+enum {
+    BITS_PER_SAMPLE = 16,
+    BYTES_PER_SAMPLE = 2,
+    TIFF_IFD_0 = 0
+};
+
+// ----------------------------------------------------------------------------
+
+// This class is not intended to be used across JNI calls.
+class JniOutputStream : public Output, public LightRefBase<JniOutputStream> {
+public:
+    JniOutputStream(JNIEnv* env, jobject outStream);
+
+    virtual ~JniOutputStream();
+
+    status_t open();
+    status_t write(const uint8_t* buf, size_t offset, size_t count);
+    status_t close();
+private:
+    enum {
+        BYTE_ARRAY_LENGTH = 1024
+    };
+    jobject mOutputStream;
+    JNIEnv* mEnv;
+    jbyteArray mByteArray;
+};
+
+JniOutputStream::JniOutputStream(JNIEnv* env, jobject outStream) : mOutputStream(outStream),
+        mEnv(env) {
+    mByteArray = env->NewByteArray(BYTE_ARRAY_LENGTH);
+    if (mByteArray == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", "Could not allocate byte array.");
+    }
+}
+
+JniOutputStream::~JniOutputStream() {
+    mEnv->DeleteLocalRef(mByteArray);
+}
+
+status_t JniOutputStream::open() {
+    // Do nothing
+    return OK;
+}
+
+status_t JniOutputStream::write(const uint8_t* buf, size_t offset, size_t count) {
+    while(count > 0) {
+        size_t len = BYTE_ARRAY_LENGTH;
+        len = (count > len) ? len : count;
+        mEnv->SetByteArrayRegion(mByteArray, 0, len, reinterpret_cast<const jbyte*>(buf + offset));
+
+        if (mEnv->ExceptionCheck()) {
+            return BAD_VALUE;
+        }
+
+        mEnv->CallVoidMethod(mOutputStream, gOutputStreamClassInfo.mWriteMethod, mByteArray,
+                0, len);
+
+        if (mEnv->ExceptionCheck()) {
+            return BAD_VALUE;
+        }
+
+        count -= len;
+        offset += len;
+    }
+    return OK;
+}
+
+status_t JniOutputStream::close() {
+    // Do nothing
+    return OK;
+}
+
+// ----------------------------------------------------------------------------
+
+extern "C" {
+
+static TiffWriter* DngCreator_getCreator(JNIEnv* env, jobject thiz) {
+    ALOGV("%s:", __FUNCTION__);
+    return reinterpret_cast<TiffWriter*>(env->GetLongField(thiz,
+            gDngCreatorClassInfo.mNativeContext));
+}
+
+static void DngCreator_setCreator(JNIEnv* env, jobject thiz, sp<TiffWriter> writer) {
+    ALOGV("%s:", __FUNCTION__);
+    TiffWriter* current = DngCreator_getCreator(env, thiz);
+    if (writer != NULL) {
+        writer->incStrong((void*) DngCreator_setCreator);
+    }
+    if (current) {
+        current->decStrong((void*) DngCreator_setCreator);
+    }
+    env->SetLongField(thiz, gDngCreatorClassInfo.mNativeContext,
+            reinterpret_cast<jlong>(writer.get()));
+}
+
+static void DngCreator_nativeClassInit(JNIEnv* env, jclass clazz) {
+    ALOGV("%s:", __FUNCTION__);
+
+    gDngCreatorClassInfo.mNativeContext = env->GetFieldID(clazz,
+            ANDROID_MEDIA_DNGCREATOR_CTX_JNI_ID, "J");
+    LOG_ALWAYS_FATAL_IF(gDngCreatorClassInfo.mNativeContext == NULL,
+            "can't find android/media/DngCreator.%s", ANDROID_MEDIA_DNGCREATOR_CTX_JNI_ID);
+
+    jclass outputStreamClazz = env->FindClass("java/io/OutputStream");
+    LOG_ALWAYS_FATAL_IF(outputStreamClazz == NULL, "Can't find java/io/OutputStream class");
+    gOutputStreamClassInfo.mWriteMethod = env->GetMethodID(outputStreamClazz, "write", "([BII)V");
+    LOG_ALWAYS_FATAL_IF(gOutputStreamClassInfo.mWriteMethod == NULL, "Can't find write method");
+}
+
+static void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPtr,
+        jobject resultsPtr) {
+    ALOGV("%s:", __FUNCTION__);
+    CameraMetadata characteristics;
+    CameraMetadata results;
+    if (CameraMetadata_getNativeMetadata(env, characteristicsPtr, &characteristics) != OK) {
+         jniThrowException(env, "java/lang/AssertionError",
+                "No native metadata defined for camera characteristics.");
+         return;
+    }
+    if (CameraMetadata_getNativeMetadata(env, resultsPtr, &results) != OK) {
+        jniThrowException(env, "java/lang/AssertionError",
+                "No native metadata defined for capture results.");
+        return;
+    }
+
+    sp<TiffWriter> writer = new TiffWriter();
+
+    writer->addIfd(TIFF_IFD_0);
+
+    status_t err = OK;
+
+    const uint32_t samplesPerPixel = 1;
+    const uint32_t bitsPerSample = BITS_PER_SAMPLE;
+    const uint32_t bitsPerByte = BITS_PER_SAMPLE / BYTES_PER_SAMPLE;
+    uint32_t imageWidth = 0;
+    uint32_t imageHeight = 0;
+
+    OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+
+    // TODO: Greensplit.
+    // TODO: UniqueCameraModel
+    // TODO: Add remaining non-essential tags
+    {
+        // Set orientation
+        uint16_t orientation = 1; // Normal
+        BAIL_IF_INVALID(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0), env,
+                TAG_ORIENTATION);
+    }
+
+    {
+        // Set subfiletype
+        uint32_t subfileType = 0; // Main image
+        BAIL_IF_INVALID(writer->addEntry(TAG_NEWSUBFILETYPE, 1, &subfileType, TIFF_IFD_0), env,
+                TAG_NEWSUBFILETYPE);
+    }
+
+    {
+        // Set bits per sample
+        uint16_t bits = static_cast<uint16_t>(bitsPerSample);
+        BAIL_IF_INVALID(writer->addEntry(TAG_BITSPERSAMPLE, 1, &bits, TIFF_IFD_0), env,
+                TAG_BITSPERSAMPLE);
+    }
+
+    {
+        // Set compression
+        uint16_t compression = 1; // None
+        BAIL_IF_INVALID(writer->addEntry(TAG_COMPRESSION, 1, &compression, TIFF_IFD_0), env,
+                TAG_COMPRESSION);
+    }
+
+    {
+        // Set dimensions
+        camera_metadata_entry entry =
+                characteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+        BAIL_IF_EMPTY(entry, env, TAG_IMAGEWIDTH);
+        uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
+        uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
+        BAIL_IF_INVALID(writer->addEntry(TAG_IMAGEWIDTH, 1, &width, TIFF_IFD_0), env,
+                TAG_IMAGEWIDTH);
+        BAIL_IF_INVALID(writer->addEntry(TAG_IMAGELENGTH, 1, &height, TIFF_IFD_0), env,
+                TAG_IMAGELENGTH);
+        imageWidth = width;
+        imageHeight = height;
+    }
+
+    {
+        // Set photometric interpretation
+        uint16_t interpretation = 32803;
+        BAIL_IF_INVALID(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1, &interpretation,
+                TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION);
+    }
+
+    {
+        // Set blacklevel tags
+        camera_metadata_entry entry =
+                characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
+        BAIL_IF_EMPTY(entry, env, TAG_BLACKLEVEL);
+        const uint32_t* blackLevel = reinterpret_cast<const uint32_t*>(entry.data.i32);
+        BAIL_IF_INVALID(writer->addEntry(TAG_BLACKLEVEL, entry.count, blackLevel, TIFF_IFD_0), env,
+                TAG_BLACKLEVEL);
+
+        uint16_t repeatDim[2] = {2, 2};
+        BAIL_IF_INVALID(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim, TIFF_IFD_0), env,
+                TAG_BLACKLEVELREPEATDIM);
+    }
+
+    {
+        // Set samples per pixel
+        uint16_t samples = static_cast<uint16_t>(samplesPerPixel);
+        BAIL_IF_INVALID(writer->addEntry(TAG_SAMPLESPERPIXEL, 1, &samples, TIFF_IFD_0),
+                env, TAG_SAMPLESPERPIXEL);
+    }
+
+    {
+        // Set planar configuration
+        uint16_t config = 1; // Chunky
+        BAIL_IF_INVALID(writer->addEntry(TAG_PLANARCONFIGURATION, 1, &config, TIFF_IFD_0),
+                env, TAG_PLANARCONFIGURATION);
+    }
+
+    {
+        // Set CFA pattern dimensions
+        uint16_t repeatDim[2] = {2, 2};
+        BAIL_IF_INVALID(writer->addEntry(TAG_CFAREPEATPATTERNDIM, 2, repeatDim, TIFF_IFD_0),
+                env, TAG_CFAREPEATPATTERNDIM);
+    }
+
+    {
+        // Set CFA pattern
+        camera_metadata_entry entry =
+                        characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+        BAIL_IF_EMPTY(entry, env, TAG_CFAPATTERN);
+        camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
+                static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
+                entry.data.u8[0]);
+        switch(cfa) {
+            case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
+                uint8_t cfa[4] = {0, 1, 1, 2};
+                BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
+                                                env, TAG_CFAPATTERN);
+                opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+                break;
+            }
+            case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
+                uint8_t cfa[4] = {1, 0, 2, 1};
+                BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
+                                                env, TAG_CFAPATTERN);
+                opcodeCfaLayout = OpcodeListBuilder::CFA_GRBG;
+                break;
+            }
+            case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
+                uint8_t cfa[4] = {1, 2, 0, 1};
+                BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
+                                                env, TAG_CFAPATTERN);
+                opcodeCfaLayout = OpcodeListBuilder::CFA_GBRG;
+                break;
+            }
+            case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
+                uint8_t cfa[4] = {2, 1, 1, 0};
+                BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
+                                env, TAG_CFAPATTERN);
+                opcodeCfaLayout = OpcodeListBuilder::CFA_BGGR;
+                break;
+            }
+            default: {
+                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                            "Invalid metadata for tag %d", TAG_CFAPATTERN);
+                return;
+            }
+        }
+    }
+
+    {
+        // Set CFA plane color
+        uint8_t cfaPlaneColor[3] = {0, 1, 2};
+        BAIL_IF_INVALID(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor, TIFF_IFD_0),
+                env, TAG_CFAPLANECOLOR);
+    }
+
+    {
+        // Set CFA layout
+        uint16_t cfaLayout = 1;
+        BAIL_IF_INVALID(writer->addEntry(TAG_CFALAYOUT, 1, &cfaLayout, TIFF_IFD_0),
+                env, TAG_CFALAYOUT);
+    }
+
+    {
+        // Set DNG version information
+        uint8_t version[4] = {1, 4, 0, 0};
+        BAIL_IF_INVALID(writer->addEntry(TAG_DNGVERSION, 4, version, TIFF_IFD_0),
+                env, TAG_DNGVERSION);
+
+        uint8_t backwardVersion[4] = {1, 1, 0, 0};
+        BAIL_IF_INVALID(writer->addEntry(TAG_DNGBACKWARDVERSION, 4, backwardVersion, TIFF_IFD_0),
+                env, TAG_DNGBACKWARDVERSION);
+    }
+
+    {
+        // Set whitelevel
+        camera_metadata_entry entry =
+                characteristics.find(ANDROID_SENSOR_INFO_WHITE_LEVEL);
+        BAIL_IF_EMPTY(entry, env, TAG_WHITELEVEL);
+        uint32_t whiteLevel = static_cast<uint32_t>(entry.data.i32[0]);
+        BAIL_IF_INVALID(writer->addEntry(TAG_WHITELEVEL, 1, &whiteLevel, TIFF_IFD_0), env,
+                TAG_WHITELEVEL);
+    }
+
+    {
+        // Set default scale
+        uint32_t defaultScale[4] = {1, 1, 1, 1};
+        BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTSCALE, 2, defaultScale, TIFF_IFD_0),
+                env, TAG_DEFAULTSCALE);
+    }
+
+    bool singleIlluminant = false;
+    {
+        // Set calibration illuminants
+        camera_metadata_entry entry1 =
+            characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT1);
+        BAIL_IF_EMPTY(entry1, env, TAG_CALIBRATIONILLUMINANT1);
+        camera_metadata_entry entry2 =
+            characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT2);
+        if (entry2.count == 0) {
+            singleIlluminant = true;
+        }
+        uint16_t ref1 = entry1.data.u8[0];
+
+        BAIL_IF_INVALID(writer->addEntry(TAG_CALIBRATIONILLUMINANT1, 1, &ref1,
+                TIFF_IFD_0), env, TAG_CALIBRATIONILLUMINANT1);
+
+        if (!singleIlluminant) {
+            uint16_t ref2 = entry2.data.u8[0];
+            BAIL_IF_INVALID(writer->addEntry(TAG_CALIBRATIONILLUMINANT2, 1, &ref2,
+                    TIFF_IFD_0), env, TAG_CALIBRATIONILLUMINANT2);
+        }
+    }
+
+    {
+        // Set color transforms
+        camera_metadata_entry entry1 =
+            characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM1);
+        BAIL_IF_EMPTY(entry1, env, TAG_COLORMATRIX1);
+
+        int32_t colorTransform1[entry1.count * 2];
+
+        size_t ctr = 0;
+        for(size_t i = 0; i < entry1.count; ++i) {
+            colorTransform1[ctr++] = entry1.data.r[i].numerator;
+            colorTransform1[ctr++] = entry1.data.r[i].denominator;
+        }
+
+        BAIL_IF_INVALID(writer->addEntry(TAG_COLORMATRIX1, entry1.count, colorTransform1, TIFF_IFD_0),
+                env, TAG_COLORMATRIX1);
+
+        if (!singleIlluminant) {
+            camera_metadata_entry entry2 = characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM2);
+            BAIL_IF_EMPTY(entry2, env, TAG_COLORMATRIX2);
+            int32_t colorTransform2[entry2.count * 2];
+
+            ctr = 0;
+            for(size_t i = 0; i < entry2.count; ++i) {
+                colorTransform2[ctr++] = entry2.data.r[i].numerator;
+                colorTransform2[ctr++] = entry2.data.r[i].denominator;
+            }
+
+            BAIL_IF_INVALID(writer->addEntry(TAG_COLORMATRIX2, entry2.count, colorTransform2, TIFF_IFD_0),
+                    env, TAG_COLORMATRIX2);
+        }
+    }
+
+    {
+        // Set calibration transforms
+        camera_metadata_entry entry1 =
+            characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM1);
+        BAIL_IF_EMPTY(entry1, env, TAG_CAMERACALIBRATION1);
+
+        int32_t calibrationTransform1[entry1.count * 2];
+
+        size_t ctr = 0;
+        for(size_t i = 0; i < entry1.count; ++i) {
+            calibrationTransform1[ctr++] = entry1.data.r[i].numerator;
+            calibrationTransform1[ctr++] = entry1.data.r[i].denominator;
+        }
+
+        BAIL_IF_INVALID(writer->addEntry(TAG_CAMERACALIBRATION1, entry1.count, calibrationTransform1,
+                TIFF_IFD_0), env, TAG_CAMERACALIBRATION1);
+
+        if (!singleIlluminant) {
+            camera_metadata_entry entry2 =
+                characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM2);
+            BAIL_IF_EMPTY(entry2, env, TAG_CAMERACALIBRATION2);
+            int32_t calibrationTransform2[entry2.count * 2];
+
+            ctr = 0;
+            for(size_t i = 0; i < entry2.count; ++i) {
+                calibrationTransform2[ctr++] = entry2.data.r[i].numerator;
+                calibrationTransform2[ctr++] = entry2.data.r[i].denominator;
+            }
+
+            BAIL_IF_INVALID(writer->addEntry(TAG_CAMERACALIBRATION2, entry2.count, calibrationTransform1,
+                    TIFF_IFD_0),  env, TAG_CAMERACALIBRATION2);
+        }
+    }
+
+    {
+        // Set forward transforms
+        camera_metadata_entry entry1 =
+            characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX1);
+        BAIL_IF_EMPTY(entry1, env, TAG_FORWARDMATRIX1);
+
+        int32_t forwardTransform1[entry1.count * 2];
+
+        size_t ctr = 0;
+        for(size_t i = 0; i < entry1.count; ++i) {
+            forwardTransform1[ctr++] = entry1.data.r[i].numerator;
+            forwardTransform1[ctr++] = entry1.data.r[i].denominator;
+        }
+
+        BAIL_IF_INVALID(writer->addEntry(TAG_FORWARDMATRIX1, entry1.count, forwardTransform1,
+                TIFF_IFD_0), env, TAG_FORWARDMATRIX1);
+
+        if (!singleIlluminant) {
+            camera_metadata_entry entry2 =
+                characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX2);
+            BAIL_IF_EMPTY(entry2, env, TAG_FORWARDMATRIX2);
+            int32_t forwardTransform2[entry2.count * 2];
+
+            ctr = 0;
+            for(size_t i = 0; i < entry2.count; ++i) {
+                forwardTransform2[ctr++] = entry2.data.r[i].numerator;
+                forwardTransform2[ctr++] = entry2.data.r[i].denominator;
+            }
+
+            BAIL_IF_INVALID(writer->addEntry(TAG_FORWARDMATRIX2, entry2.count, forwardTransform2,
+                    TIFF_IFD_0),  env, TAG_FORWARDMATRIX2);
+        }
+    }
+
+    {
+        // Set camera neutral
+        camera_metadata_entry entry =
+            results.find(ANDROID_SENSOR_NEUTRAL_COLOR_POINT);
+        BAIL_IF_EMPTY(entry, env, TAG_ASSHOTNEUTRAL);
+        uint32_t cameraNeutral[entry.count * 2];
+
+        size_t ctr = 0;
+        for(size_t i = 0; i < entry.count; ++i) {
+            cameraNeutral[ctr++] =
+                    static_cast<uint32_t>(entry.data.r[i].numerator);
+            cameraNeutral[ctr++] =
+                    static_cast<uint32_t>(entry.data.r[i].denominator);
+        }
+
+        BAIL_IF_INVALID(writer->addEntry(TAG_ASSHOTNEUTRAL, entry.count, cameraNeutral,
+                TIFF_IFD_0), env, TAG_ASSHOTNEUTRAL);
+    }
+
+    {
+        // Setup data strips
+        // TODO: Switch to tiled implementation.
+        uint32_t offset = 0;
+        BAIL_IF_INVALID(writer->addEntry(TAG_STRIPOFFSETS, 1, &offset, TIFF_IFD_0), env,
+                TAG_STRIPOFFSETS);
+
+        BAIL_IF_INVALID(writer->addEntry(TAG_ROWSPERSTRIP, 1, &imageHeight, TIFF_IFD_0), env,
+                TAG_ROWSPERSTRIP);
+
+        uint32_t byteCount = imageWidth * imageHeight * bitsPerSample * samplesPerPixel /
+                bitsPerByte;
+        BAIL_IF_INVALID(writer->addEntry(TAG_STRIPBYTECOUNTS, 1, &byteCount, TIFF_IFD_0), env,
+                TAG_STRIPBYTECOUNTS);
+    }
+
+    {
+        // Setup default crop + crop origin tags
+        uint32_t margin = 8; // Default margin recommended by Adobe for interpolation.
+        uint32_t dimensionLimit = 128; // Smallest image dimension crop margin from.
+        if (imageWidth >= dimensionLimit && imageHeight >= dimensionLimit) {
+            uint32_t defaultCropOrigin[] = {margin, margin};
+            uint32_t defaultCropSize[] = {imageWidth - margin, imageHeight - margin};
+            BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPORIGIN, 2, defaultCropOrigin,
+                    TIFF_IFD_0), env, TAG_DEFAULTCROPORIGIN);
+            BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPSIZE, 2, defaultCropSize,
+                    TIFF_IFD_0), env, TAG_DEFAULTCROPSIZE);
+        }
+    }
+
+    {
+        // Setup unique camera model tag
+        char model[PROPERTY_VALUE_MAX];
+        property_get("ro.product.model", model, "");
+
+        char manufacturer[PROPERTY_VALUE_MAX];
+        property_get("ro.product.manufacturer", manufacturer, "");
+
+        char brand[PROPERTY_VALUE_MAX];
+        property_get("ro.product.brand", brand, "");
+
+        String8 cameraModel(model);
+        cameraModel += "-";
+        cameraModel += manufacturer;
+        cameraModel += "-";
+        cameraModel += brand;
+
+        BAIL_IF_INVALID(writer->addEntry(TAG_UNIQUECAMERAMODEL, cameraModel.size() + 1,
+                reinterpret_cast<const uint8_t*>(cameraModel.string()), TIFF_IFD_0), env,
+                TAG_UNIQUECAMERAMODEL);
+    }
+
+    {
+        // Setup opcode List 2
+        camera_metadata_entry entry1 =
+                characteristics.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
+        BAIL_IF_EMPTY(entry1, env, TAG_OPCODELIST2);
+        uint32_t lsmWidth = static_cast<uint32_t>(entry1.data.i32[0]);
+        uint32_t lsmHeight = static_cast<uint32_t>(entry1.data.i32[1]);
+
+        camera_metadata_entry entry2 =
+                results.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
+        BAIL_IF_EMPTY(entry2, env, TAG_OPCODELIST2);
+        if (entry2.count == lsmWidth * lsmHeight * 4) {
+
+            OpcodeListBuilder builder;
+            status_t err = builder.addGainMapsForMetadata(lsmWidth,
+                                                          lsmHeight,
+                                                          0,
+                                                          0,
+                                                          imageHeight,
+                                                          imageWidth,
+                                                          opcodeCfaLayout,
+                                                          entry2.data.f);
+            if (err == OK) {
+                size_t listSize = builder.getSize();
+                uint8_t opcodeListBuf[listSize];
+                err = builder.buildOpList(opcodeListBuf);
+                if (err == OK) {
+                    BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf,
+                            TIFF_IFD_0), env, TAG_OPCODELIST2);
+                } else {
+                    ALOGE("%s: Could not build Lens shading map opcode.", __FUNCTION__);
+                    jniThrowRuntimeException(env, "failed to construct lens shading map opcode.");
+                }
+            } else {
+                ALOGE("%s: Could not add Lens shading map.", __FUNCTION__);
+                jniThrowRuntimeException(env, "failed to add lens shading map.");
+            }
+        } else {
+            ALOGW("%s: Lens shading map not present in results, skipping...", __FUNCTION__);
+        }
+    }
+
+    DngCreator_setCreator(env, thiz, writer);
+}
+
+static void DngCreator_destroy(JNIEnv* env, jobject thiz) {
+    ALOGV("%s:", __FUNCTION__);
+    DngCreator_setCreator(env, thiz, NULL);
+}
+
+static void DngCreator_nativeSetOrientation(JNIEnv* env, jobject thiz) {
+    ALOGV("%s:", __FUNCTION__);
+    jniThrowRuntimeException(env, "nativeSetOrientation is not implemented");
+}
+
+static void DngCreator_nativeSetThumbnailBitmap(JNIEnv* env, jobject thiz, jobject bitmap) {
+    ALOGV("%s:", __FUNCTION__);
+    jniThrowRuntimeException(env, "nativeSetThumbnailBitmap is not implemented");
+}
+
+static void DngCreator_nativeSetThumbnailImage(JNIEnv* env, jobject thiz, jint width, jint height,
+        jobject yBuffer, jint yRowStride, jint yPixStride, jobject uBuffer, jint uRowStride,
+        jint uPixStride, jobject vBuffer, jint vRowStride, jint vPixStride) {
+    ALOGV("%s:", __FUNCTION__);
+    jniThrowRuntimeException(env, "nativeSetThumbnailImage is not implemented");
+}
+
+static void DngCreator_nativeWriteImage(JNIEnv* env, jobject thiz, jobject outStream, jint width,
+        jint height, jobject inBuffer, jint rowStride, jint pixStride) {
+    ALOGV("%s:", __FUNCTION__);
+
+    sp<JniOutputStream> out = new JniOutputStream(env, outStream);
+    if(env->ExceptionCheck()) {
+        ALOGE("%s: Could not allocate buffers for output stream", __FUNCTION__);
+        return;
+    }
+
+    uint8_t* pixelBytes = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(inBuffer));
+    if (pixelBytes == NULL) {
+        ALOGE("%s: Could not get native byte buffer", __FUNCTION__);
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid bytebuffer");
+        return;
+    }
+
+    TiffWriter* writer = DngCreator_getCreator(env, thiz);
+    if (writer == NULL) {
+        ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__);
+        jniThrowException(env, "java/lang/AssertionError",
+                "Write called with uninitialized DngCreator");
+        return;
+    }
+    // TODO: handle lens shading map, etc. conversions for other raw buffer sizes.
+    uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, TIFF_IFD_0)->getData<uint32_t>());
+    uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, TIFF_IFD_0)->getData<uint32_t>());
+    if (metadataWidth != width) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException", \
+                        "Metadata width %d doesn't match image width %d", metadataWidth, width);
+        return;
+    }
+
+    if (metadataHeight != height) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException", \
+                        "Metadata height %d doesn't match image height %d", metadataHeight, height);
+        return;
+    }
+
+    uint32_t stripOffset = writer->getTotalSize();
+
+    BAIL_IF_INVALID(writer->addEntry(TAG_STRIPOFFSETS, 1, &stripOffset, TIFF_IFD_0), env,
+                    TAG_STRIPOFFSETS);
+
+    if (writer->write(out.get()) != OK) {
+        if (!env->ExceptionCheck()) {
+            jniThrowException(env, "java/io/IOException", "Failed to write metadata");
+        }
+        return;
+    }
+
+    size_t fullSize = rowStride * height;
+    jlong capacity = env->GetDirectBufferCapacity(inBuffer);
+    if (capacity < 0 || fullSize > capacity) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                "Invalid size %d for Image, size given in metadata is %d at current stride",
+                capacity, fullSize);
+        return;
+    }
+
+    if (pixStride == BYTES_PER_SAMPLE && rowStride == width * BYTES_PER_SAMPLE) {
+        if (out->write(pixelBytes, 0, fullSize) != OK || env->ExceptionCheck()) {
+            if (!env->ExceptionCheck()) {
+                jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
+            }
+            return;
+        }
+    } else if (pixStride == BYTES_PER_SAMPLE) {
+        for (size_t i = 0; i < height; ++i) {
+            if (out->write(pixelBytes, i * rowStride, pixStride * width) != OK ||
+                        env->ExceptionCheck()) {
+                if (!env->ExceptionCheck()) {
+                    jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
+                }
+                return;
+            }
+        }
+    } else {
+        for (size_t i = 0; i < height; ++i) {
+            for (size_t j = 0; j < width; ++j) {
+                if (out->write(pixelBytes, i * rowStride + j * pixStride,
+                        BYTES_PER_SAMPLE) != OK || !env->ExceptionCheck()) {
+                    if (env->ExceptionCheck()) {
+                        jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
+                    }
+                    return;
+                }
+            }
+        }
+    }
+
+}
+
+static void DngCreator_nativeWriteByteBuffer(JNIEnv* env, jobject thiz, jobject outStream,
+        jobject rawBuffer, jlong offset) {
+    ALOGV("%s:", __FUNCTION__);
+    jniThrowRuntimeException(env, "nativeWriteByteBuffer is not implemented.");
+}
+
+static void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject outStream,
+        jobject inStream, jlong offset) {
+    ALOGV("%s:", __FUNCTION__);
+    jniThrowRuntimeException(env, "nativeWriteInputStream is not implemented.");
+}
+
+} /*extern "C" */
+
+static JNINativeMethod gDngCreatorMethods[] = {
+    {"nativeClassInit",        "()V", (void*) DngCreator_nativeClassInit},
+    {"nativeInit", "(Landroid/hardware/camera2/impl/CameraMetadataNative;"
+            "Landroid/hardware/camera2/impl/CameraMetadataNative;)V", (void*) DngCreator_init},
+    {"nativeDestroy",           "()V",      (void*) DngCreator_destroy},
+    {"nativeSetOrientation",    "(I)V",     (void*) DngCreator_nativeSetOrientation},
+    {"nativeSetThumbnailBitmap","(Landroid/graphics/Bitmap;)V",
+            (void*) DngCreator_nativeSetThumbnailBitmap},
+    {"nativeSetThumbnailImage",
+            "(IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)V",
+            (void*) DngCreator_nativeSetThumbnailImage},
+    {"nativeWriteImage",        "(Ljava/io/OutputStream;IILjava/nio/ByteBuffer;II)V",
+            (void*) DngCreator_nativeWriteImage},
+    {"nativeWriteByteBuffer",    "(Ljava/io/OutputStream;Ljava/nio/ByteBuffer;J)V",
+            (void*) DngCreator_nativeWriteByteBuffer},
+    {"nativeWriteInputStream",    "(Ljava/io/OutputStream;Ljava/io/InputStream;J)V",
+            (void*) DngCreator_nativeWriteInputStream},
+};
+
+int register_android_media_DngCreator(JNIEnv *env) {
+    return AndroidRuntime::registerNativeMethods(env,
+                   "android/media/DngCreator", gDngCreatorMethods, NELEM(gDngCreatorMethods));
+}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 6f42057..9d03cc38 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -884,6 +884,7 @@
                 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
 }
 
+extern int register_android_media_DngCreator(JNIEnv *env);
 extern int register_android_media_ImageReader(JNIEnv *env);
 extern int register_android_media_Crypto(JNIEnv *env);
 extern int register_android_media_Drm(JNIEnv *env);
@@ -913,6 +914,11 @@
     }
     assert(env != NULL);
 
+    if (register_android_media_DngCreator(env) < 0) {
+        ALOGE("ERROR: ImageReader native registration failed");
+        goto bail;
+    }
+
     if (register_android_media_ImageReader(env) < 0) {
         ALOGE("ERROR: ImageReader native registration failed");
         goto bail;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8425c48..94edc07 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -42,6 +42,8 @@
     private boolean mIsBouncing;
     private SecurityCallback mSecurityCallback;
 
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+
     // Used to notify the container when something interesting happens.
     public interface SecurityCallback {
         public boolean dismiss(boolean authenticated);
@@ -62,6 +64,7 @@
         super(context, attrs, defStyle);
         mSecurityModel = new KeyguardSecurityModel(context);
         mLockPatternUtils = new LockPatternUtils(context);
+        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
     }
 
     public void setSecurityCallback(SecurityCallback callback) {
@@ -303,7 +306,9 @@
     boolean showNextSecurityScreenOrFinish(boolean authenticated) {
         if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
         boolean finish = false;
-        if (SecurityMode.None == mCurrentSecuritySelection) {
+        if (mUpdateMonitor.getUserHasTrust(mLockPatternUtils.getCurrentUser())) {
+            finish = true;
+        } else if (SecurityMode.None == mCurrentSecuritySelection) {
             SecurityMode securityMode = mSecurityModel.getSecurityMode();
             // Allow an alternate, such as biometric unlock
             securityMode = mSecurityModel.getAlternateFor(securityMode);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index 2d492db..5ef41c9 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -83,8 +83,6 @@
         } else if (simState == IccCardConstants.State.PUK_REQUIRED
                 && mLockPatternUtils.isPukUnlockScreenEnable()) {
             mode = SecurityMode.SimPuk;
-        } else if (updateMonitor.getUserHasTrust(mLockPatternUtils.getCurrentUser())) {
-            mode = SecurityMode.None;
         } else {
             final int security = mLockPatternUtils.getKeyguardStoredPasswordQuality();
             switch (security) {
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png
deleted file mode 100644
index 6f48fe8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_on.png
deleted file mode 100644
index 5f2e95a..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_not_connected.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_not_connected.png
deleted file mode 100644
index e417a19..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_not_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_off.png
deleted file mode 100644
index f325220..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_on.png
deleted file mode 100644
index ee88a1b..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_bluetooth_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png
deleted file mode 100644
index 48606a8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png
deleted file mode 100644
index d006f13..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png
deleted file mode 100644
index 867947b..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png
deleted file mode 100644
index fe6dc52..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png
deleted file mode 100644
index aea75c1..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
deleted file mode 100644
index 58f67d0..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
deleted file mode 100644
index b794c9a..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png
deleted file mode 100644
index fa23e85..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png
deleted file mode 100644
index aa8635c..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_off.png
deleted file mode 100644
index c36809b..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_on.png
deleted file mode 100644
index 6158c01..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_silent.png
deleted file mode 100644
index f3e9da2..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_silent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_vibrate.png
deleted file mode 100644
index a90aef9..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_ringer_vibrate.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_off.png
deleted file mode 100644
index 084799a..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_on.png
deleted file mode 100644
index c37ba79..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_silent.png
deleted file mode 100644
index b05bf78..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_silent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_vibrate.png
deleted file mode 100644
index 2f782cf..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_ringer_vibrate.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_off.png
deleted file mode 100644
index 714f07e..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_on.png
deleted file mode 100644
index d59f0e92..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_silent.png
deleted file mode 100644
index 8299301..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_silent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_vibrate.png
deleted file mode 100644
index e171d53..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_ringer_vibrate.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_off.png
deleted file mode 100644
index 6fc556d..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_on.png
deleted file mode 100644
index a2342fc..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_ringer_silent.png
deleted file mode 100644
index 1c847da2..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_ringer_silent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_ringer_vibrate.png
deleted file mode 100644
index d0ab910..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_ringer_vibrate.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png
deleted file mode 100644
index 95df4d45..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_on.png
deleted file mode 100644
index 251fc30..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_not_connected.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_not_connected.png
deleted file mode 100644
index b01b27f..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_not_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_off.png
deleted file mode 100644
index 541e801..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_on.png
deleted file mode 100644
index 0acf3a4..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_bluetooth_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png
deleted file mode 100644
index 25fc759..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png
deleted file mode 100644
index 9dfc3c6..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png
deleted file mode 100644
index 82f4113..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png
deleted file mode 100644
index 18b6029..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png
deleted file mode 100644
index b6ea14e..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
deleted file mode 100644
index 1e05a91..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
deleted file mode 100644
index f4afa52..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png
deleted file mode 100644
index b0185a5..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png
deleted file mode 100644
index 949ab10..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png
deleted file mode 100644
index 4411097..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_on.png
deleted file mode 100644
index 79e4ff6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_not_connected.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_not_connected.png
deleted file mode 100644
index ce965c2..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_not_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_off.png
deleted file mode 100644
index c798fd6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_on.png
deleted file mode 100644
index ac5b09d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_bluetooth_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png
deleted file mode 100644
index 945c606..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png
deleted file mode 100644
index 0a3f73e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png
deleted file mode 100644
index 398cbef..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png
deleted file mode 100644
index 95cf67f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png
deleted file mode 100644
index efd8b9e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
deleted file mode 100644
index 662d062..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
deleted file mode 100644
index 18be9c0..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png
deleted file mode 100644
index 7f7cb63..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png
deleted file mode 100644
index abdeb3b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_off.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_off.png
deleted file mode 100644
index 65b0204..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_on.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_on.png
deleted file mode 100644
index dd16165..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_airplane_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_not_connected.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_not_connected.png
deleted file mode 100644
index c5b7333..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_not_connected.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_off.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_off.png
deleted file mode 100644
index 1045e07..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_off.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_on.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_on.png
deleted file mode 100644
index 7c20110..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_bluetooth_on.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png
deleted file mode 100644
index 4621d18..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png
deleted file mode 100644
index a1ab61b..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png
deleted file mode 100644
index ea42a7f..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png
deleted file mode 100644
index 7f441c8..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png
deleted file mode 100644
index ce9bae2..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_silent.png
deleted file mode 100644
index aabf0aa..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_silent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_vibrate.png
deleted file mode 100644
index 654c2a5..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_ringer_vibrate.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png
deleted file mode 100644
index afe85b4..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png
deleted file mode 100644
index 5e5053f..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_location_off_anim.xml b/packages/SystemUI/res/drawable/ic_location_off_anim.xml
deleted file mode 100644
index 864eda1..0000000
--- a/packages/SystemUI/res/drawable/ic_location_off_anim.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="true">
-    <item android:drawable="@drawable/ic_location_24_01" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_02" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_03" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_04" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_05" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_06" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_07" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_08" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_09" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_10" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_11" android:duration="16" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_location_on_anim.xml b/packages/SystemUI/res/drawable/ic_location_on_anim.xml
deleted file mode 100644
index 65a8afe..0000000
--- a/packages/SystemUI/res/drawable/ic_location_on_anim.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="true">
-    <item android:drawable="@drawable/ic_location_24_11" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_10" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_09" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_08" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_07" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_06" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_05" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_04" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_03" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_02" android:duration="16" />
-    <item android:drawable="@drawable/ic_location_24_01" android:duration="16" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_qs_airplane.xml b/packages/SystemUI/res/drawable/ic_qs_airplane_off.xml
similarity index 85%
copy from packages/SystemUI/res/drawable/ic_qs_airplane.xml
copy to packages/SystemUI/res/drawable/ic_qs_airplane_off.xml
index ffe571f..9f0ec67 100644
--- a/packages/SystemUI/res/drawable/ic_qs_airplane.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_airplane_off.xml
@@ -23,9 +23,13 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#00000000"
+        android:stroke="#CCCCCC"
+        android:strokeWidth="1.0"
         android:pathData="M10.2,9.0"/>
     <path
-        android:fill="#FF000000"
+        android:fill="#00000000"
+        android:stroke="#CCCCCC"
+        android:strokeWidth="1.0"
         android:pathData="M21.0,16.0l0.0,-2.0l-8.0,-5.0L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5L10.0,9.0l-8.0,5.0l0.0,2.0l8.0,-2.5L10.0,19.0l-2.0,1.5L8.0,22.0l3.5,-1.0l3.5,1.0l0.0,-1.5L13.0,19.0l0.0,-5.5L21.0,16.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_airplane.xml b/packages/SystemUI/res/drawable/ic_qs_airplane_on.xml
similarity index 94%
rename from packages/SystemUI/res/drawable/ic_qs_airplane.xml
rename to packages/SystemUI/res/drawable/ic_qs_airplane_on.xml
index ffe571f..95c20bb 100644
--- a/packages/SystemUI/res/drawable/ic_qs_airplane.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_airplane_on.xml
@@ -23,9 +23,9 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M10.2,9.0"/>
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M21.0,16.0l0.0,-2.0l-8.0,-5.0L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5L10.0,9.0l-8.0,5.0l0.0,2.0l8.0,-2.5L10.0,19.0l-2.0,1.5L8.0,22.0l3.5,-1.0l3.5,1.0l0.0,-1.5L13.0,19.0l0.0,-5.5L21.0,16.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
similarity index 96%
rename from packages/SystemUI/res/drawable/ic_qs_bluetooth.xml
rename to packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
index 22d0dcf..61a7777 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M17.7,7.7L12.0,2.0l-1.0,0.0l0.0,7.6L6.4,5.0L5.0,6.4l5.6,5.6L5.0,17.6L6.4,19.0l4.6,-4.6L11.0,22.0l1.0,0.0l5.7,-5.7L13.4,12.0L17.7,7.7zM13.0,5.8l1.9,1.9L13.0,9.6L13.0,5.8zM14.9,16.3L13.0,18.2l0.0,-3.8L14.9,16.3z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
similarity index 91%
copy from packages/SystemUI/res/drawable/ic_qs_bluetooth.xml
copy to packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
index 22d0dcf..7ac1cb9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
@@ -23,6 +23,8 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#00000000"
+        android:stroke="#CCCCCC"
+        android:strokeWidth="1.0"
         android:pathData="M17.7,7.7L12.0,2.0l-1.0,0.0l0.0,7.6L6.4,5.0L5.0,6.4l5.6,5.6L5.0,17.6L6.4,19.0l4.6,-4.6L11.0,22.0l1.0,0.0l5.7,-5.7L13.4,12.0L17.7,7.7zM13.0,5.8l1.9,1.9L13.0,9.6L13.0,5.8zM14.9,16.3L13.0,18.2l0.0,-3.8L14.9,16.3z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
similarity index 96%
copy from packages/SystemUI/res/drawable/ic_qs_bluetooth.xml
copy to packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
index 22d0dcf..61a7777 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M17.7,7.7L12.0,2.0l-1.0,0.0l0.0,7.6L6.4,5.0L5.0,6.4l5.6,5.6L5.0,17.6L6.4,19.0l4.6,-4.6L11.0,22.0l1.0,0.0l5.7,-5.7L13.4,12.0L17.7,7.7zM13.0,5.8l1.9,1.9L13.0,9.6L13.0,5.8zM14.9,16.3L13.0,18.2l0.0,-3.8L14.9,16.3z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bugreport.xml b/packages/SystemUI/res/drawable/ic_qs_bugreport.xml
index 2dfe183..2958848 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bugreport.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bugreport.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M20.0,8.0l-2.8,0.0c-0.5,-0.8 -1.1,-1.5 -1.8,-2.0L17.0,4.4L15.6,3.0l-2.2,2.2C13.0,5.1 12.5,5.0 12.0,5.0s-1.0,0.1 -1.4,0.2L8.4,3.0L7.0,4.4L8.6,6.0C7.9,6.5 7.3,7.2 6.8,8.0L4.0,8.0l0.0,2.0l2.1,0.0C6.0,10.3 6.0,10.7 6.0,11.0l0.0,1.0L4.0,12.0l0.0,2.0l2.0,0.0l0.0,1.0c0.0,0.3 0.0,0.7 0.1,1.0L4.0,16.0l0.0,2.0l2.8,0.0c1.0,1.8 3.0,3.0 5.2,3.0s4.2,-1.2 5.2,-3.0L20.0,18.0l0.0,-2.0l-2.1,0.0c0.1,-0.3 0.1,-0.7 0.1,-1.0l0.0,-1.0l2.0,0.0l0.0,-2.0l-2.0,0.0l0.0,-1.0c0.0,-0.3 0.0,-0.7 -0.1,-1.0L20.0,10.0L20.0,8.0zM14.0,16.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,16.0zM14.0,12.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,12.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml b/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml
deleted file mode 100644
index 70db2a9..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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 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.
- */
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="false">
-    <item android:drawable="@drawable/ic_qs_cast_connecting_0" android:duration="500" />
-    <item android:drawable="@drawable/ic_qs_cast_connecting_1" android:duration="500" />
-    <item android:drawable="@drawable/ic_qs_cast_connecting_2" android:duration="500" />
-    <item android:drawable="@drawable/ic_qs_cast_connecting_1" android:duration="500" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast.xml b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
similarity index 92%
copy from packages/SystemUI/res/drawable/ic_qs_cast.xml
copy to packages/SystemUI/res/drawable/ic_qs_cast_off.xml
index 6f2840b..130c639 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
@@ -23,6 +23,8 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#00000000"
+        android:stroke="#CCCCCC"
+        android:strokeWidth="1.0"
         android:pathData="M21.0,3.0L3.0,3.0C1.9,3.0 1.0,3.9 1.0,5.0l0.0,3.0l2.0,0.0L3.0,5.0l18.0,0.0l0.0,14.0l-7.0,0.0l0.0,2.0l7.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L23.0,5.0C23.0,3.9 22.1,3.0 21.0,3.0zM1.0,18.0l0.0,3.0l3.0,0.0C4.0,19.3 2.7,18.0 1.0,18.0zM1.0,14.0l0.0,2.0c2.8,0.0 5.0,2.2 5.0,5.0l2.0,0.0C8.0,17.1 4.9,14.0 1.0,14.0zM1.0,10.0l0.0,2.0c5.0,0.0 9.0,4.0 9.0,9.0l2.0,0.0C12.0,14.9 7.1,10.0 1.0,10.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast.xml b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
similarity index 97%
rename from packages/SystemUI/res/drawable/ic_qs_cast.xml
rename to packages/SystemUI/res/drawable/ic_qs_cast_on.xml
index 6f2840b..6c82b1c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M21.0,3.0L3.0,3.0C1.9,3.0 1.0,3.9 1.0,5.0l0.0,3.0l2.0,0.0L3.0,5.0l18.0,0.0l0.0,14.0l-7.0,0.0l0.0,2.0l7.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L23.0,5.0C23.0,3.9 22.1,3.0 21.0,3.0zM1.0,18.0l0.0,3.0l3.0,0.0C4.0,19.3 2.7,18.0 1.0,18.0zM1.0,14.0l0.0,2.0c2.8,0.0 5.0,2.2 5.0,5.0l2.0,0.0C8.0,17.1 4.9,14.0 1.0,14.0zM1.0,10.0l0.0,2.0c5.0,0.0 9.0,4.0 9.0,9.0l2.0,0.0C12.0,14.9 7.1,10.0 1.0,10.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_close.xml b/packages/SystemUI/res/drawable/ic_qs_close.xml
index c2c72c8..dd43e6c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_close.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_close.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M19.0,6.4l-1.3999996,-1.4000001 -5.6000004,5.6000004 -5.6,-5.6000004 -1.4000001,1.4000001 5.6000004,5.6 -5.6000004,5.6000004 1.4000001,1.3999996 5.6,-5.6000004 5.6000004,5.6000004 1.3999996,-1.3999996 -5.6000004,-5.6000004z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_invert_colors.xml b/packages/SystemUI/res/drawable/ic_qs_color_inversion.xml
similarity index 97%
rename from packages/SystemUI/res/drawable/ic_qs_invert_colors.xml
rename to packages/SystemUI/res/drawable/ic_qs_color_inversion.xml
index 7c92052..dc30a53 100644
--- a/packages/SystemUI/res/drawable/ic_qs_invert_colors.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_color_inversion.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M18.939,7.244c-5.887,-5.885 -6.214,-6.214 -6.222,-6.222l-0.707,-0.737L5.088,7.207c-2.914,2.915 -3.74,6.629 -2.266,10.19c1.541,3.719 5.312,6.316 9.174,6.317l0.0,0.0c3.861,-0.001 7.636,-2.603 9.179,-6.328C22.646,13.834 21.832,10.138 18.939,7.244zM4.67,16.632c-1.149,-2.776 -0.481,-5.696 1.832,-8.011l5.494,-5.492c0.0,0.002 0.002,0.003 0.003,0.004l0.0,18.582c-0.001,0.0 -0.002,0.0 -0.003,0.0C8.922,21.714 5.91,19.624 4.67,16.632z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml b/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml
deleted file mode 100644
index cf34ba6..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ic_qs_color_space_alpha"
-    android:tint="@color/ic_qs_off" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml b/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml
deleted file mode 100644
index 1806688..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ic_qs_color_space_alpha"
-    android:tint="@color/ic_qs_on" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_hotspot.xml b/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
similarity index 93%
copy from packages/SystemUI/res/drawable/ic_qs_hotspot.xml
copy to packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
index 965e3c1..7a62212 100644
--- a/packages/SystemUI/res/drawable/ic_qs_hotspot.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
@@ -23,6 +23,8 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#00000000"
+        android:stroke="#CCCCCC"
+        android:strokeWidth="1.0"
         android:pathData="M12.0,11.0c-1.1,0.0 -2.0,0.9 -2.0,2.0c0.0,1.1 0.9,2.0 2.0,2.0c1.1,0.0 2.0,-0.9 2.0,-2.0C14.0,11.9 13.1,11.0 12.0,11.0zM18.0,13.0c0.0,-3.3 -2.7,-6.0 -6.0,-6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,2.2 1.2,4.1 3.0,5.2l1.0,-1.7c-1.2,-0.7 -2.0,-2.0 -2.0,-3.4c0.0,-2.2 1.8,-4.0 4.0,-4.0s4.0,1.8 4.0,4.0c0.0,1.5 -0.8,2.8 -2.0,3.4l1.0,1.7C16.8,17.1 18.0,15.2 18.0,13.0zM12.0,3.0C6.5,3.0 2.0,7.5 2.0,13.0c0.0,3.7 2.0,6.9 5.0,8.6l1.0,-1.7c-2.4,-1.4 -4.0,-4.0 -4.0,-6.9c0.0,-4.4 3.6,-8.0 8.0,-8.0s8.0,3.6 8.0,8.0c0.0,3.0 -1.6,5.5 -4.0,6.9l1.0,1.7c3.0,-1.7 5.0,-5.0 5.0,-8.6C22.0,7.5 17.5,3.0 12.0,3.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_hotspot.xml b/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
similarity index 97%
rename from packages/SystemUI/res/drawable/ic_qs_hotspot.xml
rename to packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
index 965e3c1..3ccdd81 100644
--- a/packages/SystemUI/res/drawable/ic_qs_hotspot.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M12.0,11.0c-1.1,0.0 -2.0,0.9 -2.0,2.0c0.0,1.1 0.9,2.0 2.0,2.0c1.1,0.0 2.0,-0.9 2.0,-2.0C14.0,11.9 13.1,11.0 12.0,11.0zM18.0,13.0c0.0,-3.3 -2.7,-6.0 -6.0,-6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,2.2 1.2,4.1 3.0,5.2l1.0,-1.7c-1.2,-0.7 -2.0,-2.0 -2.0,-3.4c0.0,-2.2 1.8,-4.0 4.0,-4.0s4.0,1.8 4.0,4.0c0.0,1.5 -0.8,2.8 -2.0,3.4l1.0,1.7C16.8,17.1 18.0,15.2 18.0,13.0zM12.0,3.0C6.5,3.0 2.0,7.5 2.0,13.0c0.0,3.7 2.0,6.9 5.0,8.6l1.0,-1.7c-2.4,-1.4 -4.0,-4.0 -4.0,-6.9c0.0,-4.4 3.6,-8.0 8.0,-8.0s8.0,3.6 8.0,8.0c0.0,3.0 -1.6,5.5 -4.0,6.9l1.0,1.7c3.0,-1.7 5.0,-5.0 5.0,-8.6C22.0,7.5 17.5,3.0 12.0,3.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml
deleted file mode 100644
index 9018a90..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ic_qs_inversion_alpha"
-    android:tint="@color/ic_qs_off" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml
deleted file mode 100644
index 9110201..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ic_qs_inversion_alpha"
-    android:tint="@color/ic_qs_on" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_location.xml b/packages/SystemUI/res/drawable/ic_qs_location.xml
deleted file mode 100644
index e6e98a0..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_location.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android" >
-    <size
-        android:width="64dp"
-        android:height="64dp"/>
-
-    <viewport
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"/>
-
-    <path
-        android:fill="#FF000000"
-        android:pathData="M12.0,2.0C8.1,2.0 5.0,5.1 5.0,9.0c0.0,5.2 7.0,13.0 7.0,13.0s7.0,-7.8 7.0,-13.0C19.0,5.1 15.9,2.0 12.0,2.0zM12.0,11.5c-1.4,0.0 -2.5,-1.1 -2.5,-2.5s1.1,-2.5 2.5,-2.5c1.4,0.0 2.5,1.1 2.5,2.5S13.4,11.5 12.0,11.5z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_location_24_01.xml b/packages/SystemUI/res/drawable/ic_qs_location_01.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_01.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_01.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_02.xml b/packages/SystemUI/res/drawable/ic_qs_location_02.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_02.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_02.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_03.xml b/packages/SystemUI/res/drawable/ic_qs_location_03.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_03.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_03.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_04.xml b/packages/SystemUI/res/drawable/ic_qs_location_04.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_04.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_04.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_05.xml b/packages/SystemUI/res/drawable/ic_qs_location_05.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_05.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_05.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_06.xml b/packages/SystemUI/res/drawable/ic_qs_location_06.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_06.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_06.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_07.xml b/packages/SystemUI/res/drawable/ic_qs_location_07.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_07.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_07.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_08.xml b/packages/SystemUI/res/drawable/ic_qs_location_08.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_08.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_08.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_09.xml b/packages/SystemUI/res/drawable/ic_qs_location_09.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_09.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_09.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_10.xml b/packages/SystemUI/res/drawable/ic_qs_location_10.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_10.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_10.xml
diff --git a/packages/SystemUI/res/drawable/ic_location_24_11.xml b/packages/SystemUI/res/drawable/ic_qs_location_11.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_location_24_11.xml
rename to packages/SystemUI/res/drawable/ic_qs_location_11.xml
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_off.xml b/packages/SystemUI/res/drawable/ic_qs_location_off.xml
new file mode 100644
index 0000000..d28d347
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_location_off.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="true">
+    <item android:drawable="@drawable/ic_qs_location_01" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_02" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_03" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_04" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_05" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_06" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_07" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_08" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_09" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_10" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_11" android:duration="16" />
+</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_on.xml b/packages/SystemUI/res/drawable/ic_qs_location_on.xml
new file mode 100644
index 0000000..72512ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_location_on.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="true">
+    <item android:drawable="@drawable/ic_qs_location_11" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_10" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_09" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_08" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_07" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_06" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_05" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_04" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_03" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_02" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_location_01" android:duration="16" />
+</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_qs_minus.xml b/packages/SystemUI/res/drawable/ic_qs_minus.xml
index 8323e89..376cc28 100644
--- a/packages/SystemUI/res/drawable/ic_qs_minus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_minus.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M7.0,11.0l0.0,2.0l10.0,0.0l0.0,-2.0L7.0,11.0zM12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,20.0c-4.4,0.0 -8.0,-3.6 -8.0,-8.0s3.6,-8.0 8.0,-8.0c4.4,0.0 8.0,3.6 8.0,8.0S16.4,20.0 12.0,20.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_plus.xml b/packages/SystemUI/res/drawable/ic_qs_plus.xml
index 84cd72a..a315f7f 100644
--- a/packages/SystemUI/res/drawable/ic_qs_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_plus.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M13.0,7.0l-2.0,0.0l0.0,4.0L7.0,11.0l0.0,2.0l4.0,0.0l0.0,4.0l2.0,0.0l0.0,-4.0l4.0,0.0l0.0,-2.0l-4.0,0.0L13.0,7.0zM12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,20.0c-4.4,0.0 -8.0,-3.6 -8.0,-8.0s3.6,-8.0 8.0,-8.0c4.4,0.0 8.0,3.6 8.0,8.0S16.4,20.0 12.0,20.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_ringer_audible.xml b/packages/SystemUI/res/drawable/ic_qs_ringer_audible.xml
index fa6f20c..3a20c58 100644
--- a/packages/SystemUI/res/drawable/ic_qs_ringer_audible.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_ringer_audible.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
-        android:pathData="M3.0,9.0c0.0,0.0 0.0,6.0 0.0,6.0l4.0,0.0l5.0,5.0L12.0,4.0L7.0,9.0L3.0,9.0zM16.5,12.0c0.0,-1.8 -1.0,-3.3 -2.5,-4.0L14.0,16.0C15.5,15.3 16.5,13.8 16.5,12.0zM14.0,3.2l0.0,2.1c2.9,0.9 5.0,3.5 5.0,6.7s-2.1,5.8 -5.0,6.7l0.0,2.1c4.0,-0.9 7.0,-4.5 7.0,-8.8S18.0,4.1 14.0,3.2z"/>
+        android:fill="#FFFFFFFF"
+        android:pathData="M6.6,3.6L5.2,2.2C2.8,4.0 1.2,6.8 1.0,10.0l2.0,0.0C3.2,7.3 4.5,5.0 6.6,3.6zM20.0,10.0l2.0,0.0c-0.2,-3.2 -1.7,-6.0 -4.1,-7.8l-1.4,1.4C18.5,5.0 19.8,7.3 20.0,10.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0l-2.0,-2.0L18.0,10.5zM11.5,22.0c0.1,0.0 0.3,0.0 0.4,0.0c0.7,-0.1 1.2,-0.6 1.4,-1.2c0.1,-0.2 0.2,-0.5 0.2,-0.8l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_ringer_silent.xml b/packages/SystemUI/res/drawable/ic_qs_ringer_silent.xml
index 0665196..dd6be76 100644
--- a/packages/SystemUI/res/drawable/ic_qs_ringer_silent.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_ringer_silent.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
-        android:pathData="M16.5,12.0c0.0,-1.8 -1.0,-3.3 -2.5,-4.0l0.0,2.2l2.5,2.5C16.5,12.4 16.5,12.2 16.5,12.0zM19.0,12.0c0.0,0.9 -0.2,1.8 -0.5,2.6l1.5,1.5c0.7,-1.2 1.0,-2.7 1.0,-4.2c0.0,-4.3 -3.0,-7.9 -7.0,-8.8l0.0,2.1C16.9,6.2 19.0,8.8 19.0,12.0zM4.3,3.0L3.0,4.3L7.7,9.0L3.0,9.0c0.0,0.0 0.0,6.0 0.0,6.0l4.0,0.0l5.0,5.0l0.0,-6.7l4.3,4.3c-0.7,0.5 -1.4,0.9 -2.3,1.2l0.0,2.1c1.4,-0.3 2.6,-0.9 3.7,-1.8l2.0,2.0l1.3,-1.3l-9.0,-9.0L4.3,3.0zM12.0,4.0L9.9,6.1L12.0,8.2L12.0,4.0z"/>
+        android:fill="#FFFFFFFF"
+        android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7C9.5,4.3 9.0,4.5 8.6,4.7l9.4,9.4L18.0,10.5zM17.7,19.0l2.0,2.0l1.3,-1.3L4.3,3.0L3.0,4.3l2.9,2.9C5.3,8.2 5.0,9.3 5.0,10.5L5.0,16.0l-2.0,2.0l0.0,1.0L17.7,19.0z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_qs_ringer_vibrate.xml
index 299a2ef..96d20e8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_ringer_vibrate.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_ringer_vibrate.xml
@@ -23,6 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
+        android:fill="#FFFFFFFF"
         android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_01.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_01.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_01.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_01.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_02.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_02.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_02.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_02.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_03.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_03.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_03.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_03.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_04.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_04.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_04.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_04.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_05.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_05.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_05.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_05.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_06.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_06.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_06.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_06.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_07.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_07.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_07.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_07.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_08.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_08.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_08.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_08.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_09.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_09.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_09.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_09.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_10.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_10.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_10.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_10.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_11.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_11.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_11.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_11.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_12.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_12.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_12.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_12.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_13.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_13.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_13.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_13.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_14.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_14.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_14.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_14.xml
diff --git a/packages/SystemUI/res/drawable/ic_rotate_24_15.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_15.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_rotate_24_15.xml
rename to packages/SystemUI/res/drawable/ic_qs_rotation_15.xml
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_locked.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_locked.xml
new file mode 100644
index 0000000..75e20f0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_rotation_locked.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="true">
+    <item android:drawable="@drawable/ic_qs_rotation_01" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_02" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_03" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_04" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_05" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_06" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_07" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_08" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_09" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_10" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_11" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_12" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_13" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_14" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_15" android:duration="16" />
+</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
new file mode 100644
index 0000000..a1cedb9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="true">
+    <item android:drawable="@drawable/ic_qs_rotation_15" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_14" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_13" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_12" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_11" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_10" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_09" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_08" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_07" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_06" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_05" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_04" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_03" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_02" android:duration="16" />
+    <item android:drawable="@drawable/ic_qs_rotation_01" android:duration="16" />
+</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_qs_zen.xml b/packages/SystemUI/res/drawable/ic_qs_zen_off.xml
similarity index 66%
copy from packages/SystemUI/res/drawable/ic_qs_zen.xml
copy to packages/SystemUI/res/drawable/ic_qs_zen_off.xml
index 059c068..73886ec 100644
--- a/packages/SystemUI/res/drawable/ic_qs_zen.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_zen_off.xml
@@ -23,6 +23,8 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
-        android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0zM14.0,9.8l-2.8,3.4L14.0,13.200001L14.0,15.0L9.0,15.0l0.0,-1.8l2.8,-3.4L9.0,9.799999L9.0,8.0l5.0,0.0L14.0,9.8z"/>
+        android:fill="#00000000"
+        android:stroke="#CCCCCC"
+        android:strokeWidth="1.0"
+        android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_airplane.xml b/packages/SystemUI/res/drawable/ic_qs_zen_on.xml
similarity index 70%
copy from packages/SystemUI/res/drawable/ic_qs_airplane.xml
copy to packages/SystemUI/res/drawable/ic_qs_zen_on.xml
index ffe571f..8dff318 100644
--- a/packages/SystemUI/res/drawable/ic_qs_airplane.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_zen_on.xml
@@ -23,9 +23,6 @@
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
-        android:pathData="M10.2,9.0"/>
-    <path
-        android:fill="#FF000000"
-        android:pathData="M21.0,16.0l0.0,-2.0l-8.0,-5.0L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5L10.0,9.0l-8.0,5.0l0.0,2.0l8.0,-2.5L10.0,19.0l-2.0,1.5L8.0,22.0l3.5,-1.0l3.5,1.0l0.0,-1.5L13.0,19.0l0.0,-5.5L21.0,16.0z"/>
+        android:fill="#FFFFFFFF"
+        android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_rotate_locked_anim.xml b/packages/SystemUI/res/drawable/ic_rotate_locked_anim.xml
deleted file mode 100644
index e14a1ce..0000000
--- a/packages/SystemUI/res/drawable/ic_rotate_locked_anim.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="true">
-    <item android:drawable="@drawable/ic_rotate_24_01" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_02" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_03" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_04" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_05" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_06" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_07" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_08" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_09" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_10" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_11" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_12" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_13" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_14" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_15" android:duration="16" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_rotate_unlocked_anim.xml b/packages/SystemUI/res/drawable/ic_rotate_unlocked_anim.xml
deleted file mode 100644
index 63b8c5f..0000000
--- a/packages/SystemUI/res/drawable/ic_rotate_unlocked_anim.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="true">
-    <item android:drawable="@drawable/ic_rotate_24_15" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_14" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_13" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_12" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_11" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_10" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_09" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_08" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_07" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_06" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_05" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_04" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_03" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_02" android:duration="16" />
-    <item android:drawable="@drawable/ic_rotate_24_01" android:duration="16" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_qs_zen.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml
similarity index 66%
rename from packages/SystemUI/res/drawable/ic_qs_zen.xml
rename to packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml
index 059c068..5efd8ec 100644
--- a/packages/SystemUI/res/drawable/ic_qs_zen.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml
@@ -15,14 +15,14 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
     <size
-        android:width="64dp"
-        android:height="64dp"/>
+        android:width="19dp"
+        android:height="19dp"/>
 
     <viewport
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
-        android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0zM14.0,9.8l-2.8,3.4L14.0,13.200001L14.0,15.0L9.0,15.0l0.0,-1.8l2.8,-3.4L9.0,9.799999L9.0,8.0l5.0,0.0L14.0,9.8z"/>
+        android:fill="#FFFFFFFF"
+        android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7C9.5,4.3 9.0,4.5 8.6,4.7l9.4,9.4L18.0,10.5zM17.7,19.0l2.0,2.0l1.3,-1.3L4.3,3.0L3.0,4.3l2.9,2.9C5.3,8.2 5.0,9.3 5.0,10.5L5.0,16.0l-2.0,2.0l0.0,1.0L17.7,19.0z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_airplane.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml
similarity index 62%
copy from packages/SystemUI/res/drawable/ic_qs_airplane.xml
copy to packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml
index ffe571f..e1d63c3 100644
--- a/packages/SystemUI/res/drawable/ic_qs_airplane.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml
@@ -15,17 +15,14 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
     <size
-        android:width="64dp"
-        android:height="64dp"/>
+        android:width="20dp"
+        android:height="20dp"/>
 
     <viewport
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
-        android:pathData="M10.2,9.0"/>
-    <path
-        android:fill="#FF000000"
-        android:pathData="M21.0,16.0l0.0,-2.0l-8.0,-5.0L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5L10.0,9.0l-8.0,5.0l0.0,2.0l8.0,-2.5L10.0,19.0l-2.0,1.5L8.0,22.0l3.5,-1.0l3.5,1.0l0.0,-1.5L13.0,19.0l0.0,-5.5L21.0,16.0z"/>
+        android:fill="#FFFFFFFF"
+        android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_airplane.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_zen.xml
similarity index 65%
copy from packages/SystemUI/res/drawable/ic_qs_airplane.xml
copy to packages/SystemUI/res/drawable/stat_sys_ringer_zen.xml
index ffe571f..afab88f 100644
--- a/packages/SystemUI/res/drawable/ic_qs_airplane.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_ringer_zen.xml
@@ -15,17 +15,14 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
     <size
-        android:width="64dp"
-        android:height="64dp"/>
+        android:width="19dp"
+        android:height="19dp"/>
 
     <viewport
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"/>
 
     <path
-        android:fill="#FF000000"
-        android:pathData="M10.2,9.0"/>
-    <path
-        android:fill="#FF000000"
-        android:pathData="M21.0,16.0l0.0,-2.0l-8.0,-5.0L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5L10.0,9.0l-8.0,5.0l0.0,2.0l8.0,-2.5L10.0,19.0l-2.0,1.5L8.0,22.0l3.5,-1.0l3.5,1.0l0.0,-1.5L13.0,19.0l0.0,-5.5L21.0,16.0z"/>
+        android:fill="#FFFFFFFF"
+        android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0c5.5,0.0 10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM4.0,12.0c0.0,-4.4 3.6,-8.0 8.0,-8.0c1.8,0.0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4.0,13.8 4.0,12.0zM12.0,20.0c-1.8,0.0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20.0,10.2 20.0,12.0C20.0,16.4 16.4,20.0 12.0,20.0z" />
 </vector>
diff --git a/packages/SystemUI/res/layout/qs_zen_mode_detail.xml b/packages/SystemUI/res/layout/qs_zen_mode_detail.xml
index 2df6d43..b73874a 100644
--- a/packages/SystemUI/res/layout/qs_zen_mode_detail.xml
+++ b/packages/SystemUI/res/layout/qs_zen_mode_detail.xml
@@ -19,8 +19,9 @@
     android:layout_height="match_parent"
     android:background="@color/system_secondary_color" >
 
-    <com.android.systemui.qs.QSImageView
+    <ImageView
         android:id="@android:id/button1"
+        android:src="@drawable/ic_qs_close"
         android:layout_width="64dp"
         android:layout_height="64dp"
         android:layout_alignParentStart="true"
diff --git a/packages/SystemUI/res/layout/qs_zen_mode_detail_condition.xml b/packages/SystemUI/res/layout/qs_zen_mode_detail_condition.xml
index a5c8903..7e02bee 100644
--- a/packages/SystemUI/res/layout/qs_zen_mode_detail_condition.xml
+++ b/packages/SystemUI/res/layout/qs_zen_mode_detail_condition.xml
@@ -38,8 +38,9 @@
         android:maxLines="1"
         android:text="@string/accessibility_back" />
 
-    <com.android.systemui.qs.QSImageView
+    <ImageView
         android:id="@android:id/button1"
+        android:src="@drawable/ic_qs_plus"
         android:layout_width="64dp"
         android:layout_height="64dp"
         android:layout_alignParentEnd="true"
@@ -47,8 +48,9 @@
         android:padding="@dimen/quick_settings_panel_padding"
         android:paddingRight="0px" />
 
-    <com.android.systemui.qs.QSImageView
+    <ImageView
         android:id="@android:id/button2"
+        android:src="@drawable/ic_qs_minus"
         android:layout_width="64dp"
         android:layout_height="64dp"
         android:layout_alignParentEnd="true"
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index bda6431..a68ad2f 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -16,7 +16,8 @@
 <com.android.systemui.recents.views.TaskView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent" 
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:focusable="true">
     <com.android.systemui.recents.views.TaskThumbnailView
         android:id="@+id/task_view_thumbnail"
         android:layout_width="match_parent"
@@ -69,7 +70,7 @@
             android:layout_height="@dimen/recents_task_view_application_icon_size"
             android:layout_gravity="center_vertical|end"
             android:padding="23dp"
-            android:src="@drawable/recents_dismiss_dark" />
+            android:src="@drawable/recents_dismiss_light" />
     </com.android.systemui.recents.views.TaskBarView>
 </com.android.systemui.recents.views.TaskView>
 
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 585658e..eaa2558 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -61,11 +61,6 @@
                 android:src="@drawable/stat_notify_more"
                 android:visibility="gone"
                 />
-            <com.android.systemui.statusbar.StatusBarIconView android:id="@+id/modeIcon"
-                android:layout_width="@dimen/status_bar_icon_size"
-                android:layout_height="match_parent"
-                android:visibility="gone"
-                />
             <com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index cba13004..77b4843 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -41,8 +41,6 @@
     <color name="system_secondary_color">#ff384248</color>
     <color name="system_accent_color">#ff7fcac3</color>
     <color name="system_error_color">#fff0592b</color>
-    <color name="quick_settings_tile_icon_enabled">#ffffffff</color>
-    <color name="quick_settings_tile_icon_disabled">#ffcccccc</color>
     <color name="quick_settings_tile_divider">#ff888888</color>
     <color name="quick_settings_tile_text">#FFFFFFFF</color>
     <color name="status_bar_clock_color">#FFFFFFFF</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c15f25f..29955dd 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -284,7 +284,6 @@
     <dimen name="quick_settings_tmp_scrim_stroke_width">8dp</dimen>
     <dimen name="quick_settings_tmp_scrim_text_size">30dp</dimen>
     <dimen name="quick_settings_panel_padding">16dp</dimen>
-    <dimen name="quick_settings_tile_icon_outline">2dp</dimen>
     <dimen name="quick_settings_tile_text_size">12sp</dimen>
     <dimen name="quick_settings_tile_divider_height">1dp</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b3829a3..f5bc353 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -561,4 +561,6 @@
 
     <!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] -->
     <string name="keyguard_unlock">Swipe up to unlock</string>
+
+    <string name="bugreport_tile_extended" translatable="false">%s\n%s (%s)</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 9536b12..19888a8 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -193,4 +193,9 @@
     </style>
 
     <style name="QSBorderless" parent="@android:style/Widget.Quantum.Button.Borderless" />
+
+    <style name="QSBorderless.Tiny">
+        <item name="android:minHeight">12dip</item>
+        <item name="android:minWidth">12dip</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 323905f..105f70e 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -20,11 +20,9 @@
 import android.view.View;
 
 public interface RecentsComponent {
+    void showRecents(boolean triggeredFromAltTab, View statusBarView);
+    void hideRecents();
     void toggleRecents(Display display, int layoutDirection, View statusBarView);
-
-    void preloadRecentTasksList();
-
-    void cancelPreloadingRecentTasksList();
-
-    void closeRecents();
+    void preloadRecents();
+    void cancelPreloadingRecents();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FilterCanvas.java b/packages/SystemUI/src/com/android/systemui/qs/FilterCanvas.java
deleted file mode 100644
index 05c8ee3..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/FilterCanvas.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs;
-
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-
-/** Canvas that forwards calls to another canvas.  Can be subclassed to transform drawing calls.
- * Temporary solution to runtime modification of a single drawable shape into two
- * enabled & disabled versions.  See QSImageView. **/
-public class FilterCanvas extends Canvas {
-    private final Canvas mCanvas;
-
-    public FilterCanvas(Canvas c) {
-        mCanvas = c;
-    }
-
-    @Override
-    public void drawPath(Path path, Paint paint) {
-        mCanvas.drawPath(path, paint);
-    }
-
-    @Override
-    public int getSaveCount() {
-        return mCanvas.getSaveCount();
-    }
-
-    @Override
-    public int save() {
-        return mCanvas.save();
-    }
-
-    @Override
-    public void translate(float dx, float dy) {
-        mCanvas.translate(dx, dy);
-    }
-
-    @Override
-    public boolean clipRect(int left, int top, int right, int bottom) {
-        return mCanvas.clipRect(left, top, right, bottom);
-    }
-
-    @Override
-    public boolean clipRect(Rect rect) {
-        return mCanvas.clipRect(rect);
-    }
-
-    @Override
-    public void concat(Matrix matrix) {
-        mCanvas.concat(matrix);
-    }
-
-    @Override
-    public void restoreToCount(int saveCount) {
-        mCanvas.restoreToCount(saveCount);
-    }
-
-    @Override
-    public void drawRect(Rect r, Paint paint) {
-        mCanvas.drawRect(r, paint);
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java b/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java
index 1e15b9f..c169df0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java
@@ -21,10 +21,10 @@
 import android.os.Handler;
 import android.provider.Settings.Global;
 
-import com.android.systemui.statusbar.policy.Disposable;
+import com.android.systemui.statusbar.policy.Listenable;
 
 /** Helper for managing a global setting. **/
-public abstract class GlobalSetting extends ContentObserver implements Disposable {
+public abstract class GlobalSetting extends ContentObserver implements Listenable {
     private final Context mContext;
     private final String mSettingName;
 
@@ -34,8 +34,6 @@
         super(handler);
         mContext = context;
         mSettingName = settingName;
-        mContext.getContentResolver().registerContentObserver(
-                Global.getUriFor(mSettingName), false, this);
     }
 
     public int getValue() {
@@ -47,8 +45,13 @@
     }
 
     @Override
-    public void dispose() {
-        mContext.getContentResolver().unregisterContentObserver(this);
+    public void setListening(boolean listening) {
+        if (listening) {
+            mContext.getContentResolver().registerContentObserver(
+                    Global.getUriFor(mSettingName), false, this);
+        } else {
+            mContext.getContentResolver().unregisterContentObserver(this);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImageView.java b/packages/SystemUI/src/com/android/systemui/qs/QSImageView.java
deleted file mode 100644
index ed67560..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QSImageView.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Path;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.VectorDrawable;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import com.android.systemui.R;
-
-/** ImageView that performs runtime modification of vector drawables (using FilterCanvas). **/
-public class QSImageView extends ImageView {
-
-    private final int mOutlineWidth;
-    private final int mColorEnabled;
-    private final int mColorDisabled;
-    private FilterCanvas mFilterCanvas;
-    private Canvas mCanvas;
-    private boolean mEnabledVersion = true;
-    private boolean mFilter;
-
-    public QSImageView(Context context) {
-        this(context, null);
-    }
-
-    public QSImageView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        final Resources res = context.getResources();
-        mOutlineWidth = res.getDimensionPixelSize(R.dimen.quick_settings_tile_icon_outline);
-        mColorEnabled = res.getColor(R.color.quick_settings_tile_icon_enabled);
-        mColorDisabled = res.getColor(R.color.quick_settings_tile_icon_disabled);
-    }
-
-    public void setEnabledVersion(boolean enabledVersion) {
-        mEnabledVersion = enabledVersion;
-        invalidate();
-    }
-
-    @Override
-    public void setImageDrawable(Drawable drawable) {
-        mFilter = drawable instanceof VectorDrawable;
-        super.setImageDrawable(drawable);
-    }
-
-    @Override
-    public void setImageResource(int resId) {
-        setImageDrawable(mContext.getDrawable(resId));
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        if (mFilter) {
-            if (canvas != mCanvas) {
-                mCanvas = canvas;
-                mFilterCanvas = new QSFilterCanvas(canvas);
-            }
-            super.draw(mFilterCanvas);
-        } else {
-            super.draw(canvas);
-        }
-    }
-
-    private class QSFilterCanvas extends FilterCanvas {
-        public QSFilterCanvas(Canvas c) {
-            super(c);
-        }
-
-        @Override
-        public void drawPath(Path path, Paint paint) {
-            if (mEnabledVersion) {
-                paint.setColor(mColorEnabled);
-            } else {
-                paint.setStyle(Style.STROKE);
-                paint.setStrokeJoin(Paint.Join.ROUND);
-                paint.setColor(mColorDisabled);
-                paint.setStrokeWidth(mOutlineWidth);
-            }
-            super.drawPath(path, paint);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index afb5483..6176eb6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -80,7 +80,10 @@
             showDetail(false /*show*/, mDetailRecord);
         }
         for (TileRecord r : mRecords) {
-            r.tile.setShown(expanded);
+            r.tile.setListening(expanded);
+            if (expanded) {
+                r.tile.refreshState();
+            }
         }
     }
 
@@ -125,6 +128,7 @@
             }
         };
         r.tileView.init(click, clickSecondary);
+        r.tile.refreshState();
         mRecords.add(r);
 
         addView(r.tileView);
@@ -156,24 +160,29 @@
         mCellHeight = (int)(mCellWidth / TILE_ASPECT);
         mLargeCellWidth = (int)(mCellWidth * LARGE_TILE_FACTOR);
         mLargeCellHeight = (int)(mCellHeight * LARGE_TILE_FACTOR);
-        int r = 0;
-        int c = 0;
+        int r = -1;
+        int c = -1;
         int rows = 0;
+        boolean rowIsDual = false;
         for (TileRecord record : mRecords) {
             if (record.tileView.getVisibility() == GONE) continue;
+            // wrap to next column if we've reached the max # of columns
+            // also don't allow dual + single tiles on the same row
+            if (r == -1 || c == (mColumns - 1) || rowIsDual != record.tile.supportsDualTargets()) {
+                r++;
+                c = 0;
+                rowIsDual = record.tile.supportsDualTargets();
+            } else {
+                c++;
+            }
             record.row = r;
             record.col = c;
             rows = r + 1;
-            c++;
-            if (c == mColumns /*end of normal column*/ || r == 0 && c == 2 /*end of 1st column*/) {
-                c = 0;
-                r++;
-            }
         }
 
         for (TileRecord record : mRecords) {
             if (record.tileView.getVisibility() == GONE) continue;
-            record.tileView.setDual(record.row == 0);
+            record.tileView.setDual(record.tile.supportsDualTargets());
             final int cw = record.row == 0 ? mLargeCellWidth : mCellWidth;
             final int ch = record.row == 0 ? mLargeCellHeight : mCellHeight;
             record.tileView.measure(exactly(cw), exactly(ch));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 05f308d..835a5c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.VectorDrawable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -30,7 +29,7 @@
 import com.android.systemui.qs.QSTile.State;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.Disposable;
+import com.android.systemui.statusbar.policy.Listenable;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.RotationLockController;
@@ -47,8 +46,10 @@
  * handleUpdateState.  Callbacks affecting state should use refreshState to trigger another
  * state update pass on tile looper.
  */
-public abstract class QSTile<TState extends State> implements Disposable {
-    private final String TAG = "QSTile." + getClass().getSimpleName();
+public abstract class QSTile<TState extends State> implements Listenable {
+    protected final String TAG = "QSTile." + getClass().getSimpleName();
+    protected static final boolean DEBUG = false;
+    public static final int FEEDBACK_START_DELAY = 400;
 
     protected final Host mHost;
     protected final Context mContext;
@@ -69,6 +70,10 @@
         mHandler = new H(host.getLooper());
     }
 
+    public boolean supportsDualTargets() {
+        return false;
+    }
+
     public Host getHost() {
         return mHost;
     }
@@ -111,10 +116,6 @@
         mHandler.obtainMessage(H.USER_SWITCH, newUserId).sendToTarget();
     }
 
-    public void setShown(boolean shown) {
-        mHandler.obtainMessage(H.SHOWN, shown ? 1 : 0, 0).sendToTarget();
-    }
-
     // call only on tile worker looper
 
     private void handleSetCallback(Callback callback) {
@@ -126,10 +127,6 @@
         // optional
     }
 
-    protected void handleShown(boolean shown) {
-        // optional, discouraged
-    }
-
     protected void handleRefreshState(Object arg) {
         handleUpdateState(mTmpState, arg);
         final boolean changed = mTmpState.copyTo(mState);
@@ -161,7 +158,6 @@
         private static final int REFRESH_STATE = 4;
         private static final int SHOW_DETAIL = 5;
         private static final int USER_SWITCH = 6;
-        private static final int SHOWN = 7;
 
         private H(Looper looper) {
             super(looper);
@@ -189,9 +185,6 @@
                 } else if (msg.what == USER_SWITCH) {
                     name = "handleUserSwitch";
                     handleUserSwitch(msg.arg1);
-                } else if (msg.what == SHOWN) {
-                    name = "handleShown";
-                    handleShown(msg.arg1 != 0);
                 }
             } catch (Throwable t) {
                 final String error = "Error in " + name;
@@ -212,7 +205,6 @@
         void collapsePanels();
         Looper getLooper();
         Context getContext();
-        VectorDrawable getVectorDrawable(int resId);
         BluetoothController getBluetoothController();
         LocationController getLocationController();
         RotationLockController getRotationLockController();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 17a95fb..4cfb636 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -25,9 +25,11 @@
 import android.os.Looper;
 import android.os.Message;
 import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
 import android.widget.TextView;
 
@@ -43,9 +45,9 @@
     protected final Context mContext;
     private final View mIcon;
     private final View mDivider;
-    private final TextView mLabel;
     private final H mHandler = new H();
 
+    private TextView mLabel;
     private boolean mDual;
     private OnClickListener mClickPrimary;
     private OnClickListener mClickSecondary;
@@ -55,14 +57,7 @@
 
         mContext = context;
         final Resources res = context.getResources();
-        mLabel = new TextView(mContext);
-        mLabel.setId(android.R.id.title);
-        mLabel.setTextColor(res.getColor(R.color.quick_settings_tile_text));
-        mLabel.setGravity(Gravity.CENTER);
-        mLabel.setTypeface(CONDENSED);
-        mLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                res.getDimensionPixelSize(R.dimen.quick_settings_tile_text_size));
-        addView(mLabel);
+        recreateLabel();
         setClipChildren(false);
 
         mIcon = createIcon();
@@ -78,8 +73,33 @@
         setBackground(getSelectableBackground());
     }
 
+    private void recreateLabel() {
+        CharSequence labelText = null;
+        if (mLabel != null) {
+            labelText = mLabel.getText();
+            removeView(mLabel);
+        }
+        final Resources res = mContext.getResources();
+        mLabel = new TextView(mDual ? new ContextThemeWrapper(mContext, R.style.QSBorderless_Tiny)
+                : mContext);
+        mLabel.setId(android.R.id.title);
+        mLabel.setTextColor(res.getColor(R.color.quick_settings_tile_text));
+        mLabel.setGravity(Gravity.CENTER);
+        mLabel.setTypeface(CONDENSED);
+        mLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                res.getDimensionPixelSize(R.dimen.quick_settings_tile_text_size));
+        if (labelText != null) {
+            mLabel.setText(labelText);
+        }
+        addView(mLabel);
+    }
+
     public void setDual(boolean dual) {
+        final boolean changed = dual != mDual;
         mDual = dual;
+        if (changed) {
+            recreateLabel();
+        }
         if (mDual) {
             setOnClickListener(mClickPrimary);
             mLabel.setClickable(true);
@@ -98,7 +118,7 @@
     }
 
     protected View createIcon() {
-        QSImageView icon = new QSImageView(mContext);
+        final ImageView icon = new ImageView(mContext);
         icon.setId(android.R.id.icon);
         icon.setScaleType(ScaleType.CENTER_INSIDE);
         return icon;
@@ -120,9 +140,10 @@
         final int iconSpec = exactly((int)mLabel.getTextSize() * 2);
         mIcon.measure(iconSpec, iconSpec);
         mLabel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
-        mLabel.measure(widthMeasureSpec, exactly(mLabel.getMeasuredHeight() + p * 2));
         if (mDual) {
             mDivider.measure(widthMeasureSpec, exactly(mDivider.getLayoutParams().height));
+        } else {
+            mLabel.measure(widthMeasureSpec, exactly(mLabel.getMeasuredHeight() + p * 2));
         }
         setMeasuredDimension(w, h);
     }
@@ -156,15 +177,12 @@
     }
 
     protected void handleStateChanged(QSTile.State state) {
-        if (mIcon instanceof QSImageView) {
-            QSImageView qsiv = (QSImageView) mIcon;
+        if (mIcon instanceof ImageView) {
+            ImageView iv = (ImageView) mIcon;
             if (state.icon != null) {
-                qsiv.setImageDrawable(state.icon);
+                iv.setImageDrawable(state.icon);
             } else if (state.iconId > 0) {
-                qsiv.setImageResource(state.iconId);
-            }
-            if (state.icon != null && state instanceof QSTile.BooleanState) {
-                qsiv.setEnabledVersion(((QSTile.BooleanState)state).value);
+                iv.setImageResource(state.iconId);
             }
         }
         mLabel.setText(state.label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
index 4debaa9..3ed3d30 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
@@ -21,10 +21,10 @@
 import android.os.Handler;
 import android.provider.Settings.Secure;
 
-import com.android.systemui.statusbar.policy.Disposable;
+import com.android.systemui.statusbar.policy.Listenable;
 
 /** Helper for managing a secure setting. **/
-public abstract class SecureSetting extends ContentObserver implements Disposable {
+public abstract class SecureSetting extends ContentObserver implements Listenable {
     private final Context mContext;
     private final String mSettingName;
 
@@ -38,8 +38,7 @@
     }
 
     public void rebindForCurrentUser() {
-        mContext.getContentResolver().registerContentObserver(
-                Secure.getUriFor(mSettingName), false, this);
+        setListening(true);
     }
 
     public int getValue() {
@@ -51,8 +50,13 @@
     }
 
     @Override
-    public void dispose() {
-        mContext.getContentResolver().unregisterContentObserver(this);
+    public void setListening(boolean listening) {
+        if (listening) {
+            mContext.getContentResolver().registerContentObserver(
+                    Secure.getUriFor(mSettingName), false, this);
+        } else {
+            mContext.getContentResolver().unregisterContentObserver(this);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 5fe8422..c0f9bf2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -39,11 +39,6 @@
                 handleRefreshState(value);
             }
         };
-
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        mContext.registerReceiver(mReceiver, filter);
-        refreshState();
     }
 
     @Override
@@ -70,7 +65,6 @@
         state.value = airplaneMode;
         state.visible = true;
         state.label = mContext.getString(R.string.quick_settings_airplane_mode_label);
-        state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_airplane);
         if (airplaneMode) {
             state.iconId =  R.drawable.ic_qs_airplane_on;
             state.contentDescription =  mContext.getString(
@@ -84,9 +78,15 @@
         }
     }
 
-    public void dispose() {
-        mSetting.dispose();
-        mContext.unregisterReceiver(mReceiver);
+    public void setListening(boolean listening) {
+        if (listening) {
+            final IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+            mContext.registerReceiver(mReceiver, filter);
+        } else {
+            mContext.unregisterReceiver(mReceiver);
+        }
+        mSetting.setListening(listening);
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 60a6047..7335ab4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -33,7 +33,11 @@
     public BluetoothTile(Host host) {
         super(host);
         mController = host.getBluetoothController();
-        mController.addStateChangedCallback(mCallback);
+    }
+
+    @Override
+    public boolean supportsDualTargets() {
+        return true;
     }
 
     @Override
@@ -42,8 +46,12 @@
     }
 
     @Override
-    public void dispose() {
-        mController.removeStateChangedCallback(mCallback);
+    public void setListening(boolean listening) {
+        if (listening) {
+            mController.addStateChangedCallback(mCallback);
+        } else {
+            mController.removeStateChangedCallback(mCallback);
+        }
     }
 
     @Override
@@ -64,14 +72,13 @@
         final boolean connected = mController.isBluetoothConnected();
         state.visible = supported;
         state.value = enabled;
-        state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_bluetooth);
         final String stateContentDescription;
         if (enabled) {
             if (connected) {
-                state.iconId = R.drawable.ic_qs_bluetooth_on;
+                state.iconId = R.drawable.ic_qs_bluetooth_connected;
                 stateContentDescription = mContext.getString(R.string.accessibility_desc_connected);
             } else {
-                state.iconId = R.drawable.ic_qs_bluetooth_not_connected;
+                state.iconId = R.drawable.ic_qs_bluetooth_on;
                 stateContentDescription = mContext.getString(R.string.accessibility_desc_on);
             }
             state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
index 0e9b9a7..fa41837 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BugreportTile.java
@@ -21,6 +21,7 @@
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
+import android.os.Build;
 import android.os.RemoteException;
 import android.provider.Settings.Global;
 import android.view.WindowManager;
@@ -51,22 +52,30 @@
     }
 
     @Override
-    public void dispose() {
-        mSetting.dispose();
+    public void setListening(boolean listening) {
+        mSetting.setListening(listening);
     }
 
     @Override
     protected void handleClick() {
-        mHost.collapsePanels();
-        mUiHandler.post(mShowDialog);
+        mHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                mHost.collapsePanels();
+                mUiHandler.post(mShowDialog);
+            }
+        }, FEEDBACK_START_DELAY);
     }
 
     @Override
     protected void handleUpdateState(State state, Object pushArg) {
         state.visible = mSetting.getValue() != 0;
-        state.iconId = com.android.internal.R.drawable.stat_sys_adb;
-        state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_bugreport);
-        state.label = mContext.getString(com.android.internal.R.string.bugreport_title);
+        state.iconId = R.drawable.ic_qs_bugreport;
+        state.label = mContext.getString(
+                R.string.bugreport_tile_extended,
+                mContext.getString(com.android.internal.R.string.bugreport_title),
+                Build.VERSION.RELEASE,
+                Build.ID);
     }
 
     private final Runnable mShowDialog = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index a3eaa2c..907c77e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -35,14 +35,9 @@
 
     private final CastController mController;
 
-    private boolean mShown;
-
     public CastTile(Host host) {
         super(host);
         mController = host.getCastController();
-        if (mController != null) {
-            mController.addCallback(mCallback);
-        }
     }
 
     @Override
@@ -51,9 +46,14 @@
     }
 
     @Override
-    public void dispose() {
+    public void setListening(boolean listening) {
         if (mController == null) return;
-        mController.removeCallback(mCallback);
+        if (listening) {
+            mController.addCallback(mCallback);
+        } else {
+            mController.removeCallback(mCallback);
+        }
+        mController.setDiscovering(listening);
     }
 
     @Override
@@ -64,17 +64,13 @@
     }
 
     @Override
-    protected void handleShown(boolean shown) {
-        if (mShown == shown) return;
-        if (mController == null) return;
-        mShown = shown;
-        mController.setDiscovering(mShown);
-    }
-
-    @Override
     protected void handleClick() {
-        mHost.collapsePanels();
-        mUiHandler.post(mShowDialog);
+        mHandler.postDelayed(new Runnable() {
+            public void run() {
+                mHost.collapsePanels();
+                mUiHandler.post(mShowDialog);
+            }
+        }, FEEDBACK_START_DELAY);
     }
 
     @Override
@@ -82,13 +78,13 @@
         state.visible = true;
         state.label = mContext
                 .getString(R.string.quick_settings_remote_display_no_connection_label);
-        state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_cast);
         if (arg instanceof CallbackInfo) {
             final CallbackInfo cb = (CallbackInfo) arg;
             if (cb.connectedRouteName != null) {
                 state.value = !cb.connecting;
             }
         }
+        state.iconId = state.value ? R.drawable.ic_qs_cast_on : R.drawable.ic_qs_cast_off;
     }
 
     private static class CallbackInfo {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 86a4e79..182a0ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -38,7 +38,6 @@
     public CellularTile(Host host) {
         super(host);
         mController = host.getNetworkController();
-        mController.addNetworkSignalChangedCallback(mCallback);
     }
 
     @Override
@@ -47,8 +46,12 @@
     }
 
     @Override
-    public void dispose() {
-        mController.removeNetworkSignalChangedCallback(mCallback);
+    public void setListening(boolean listening) {
+        if (listening) {
+            mController.addNetworkSignalChangedCallback(mCallback);
+        } else {
+            mController.removeNetworkSignalChangedCallback(mCallback);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 66740af..5301362 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -39,8 +39,6 @@
                 handleRefreshState(value);
             }
         };
-
-        refreshState();
     }
 
     @Override
@@ -49,8 +47,8 @@
     }
 
     @Override
-    public void dispose() {
-        mSetting.dispose();
+    public void setListening(boolean listening) {
+        mSetting.setListening(listening);
     }
 
     @Override
@@ -73,6 +71,6 @@
         state.visible = mVisible;
         state.value = enabled;
         state.label = mContext.getString(R.string.quick_settings_inversion_label);
-        state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_invert_colors);
+        state.iconId = R.drawable.ic_qs_color_inversion;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 1a67afc..f2ba558 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -42,7 +42,7 @@
     }
 
     @Override
-    public void dispose() {
+    public void setListening(boolean listening) {
 
     }
 
@@ -55,6 +55,6 @@
     protected void handleUpdateState(State state, Object arg) {
         state.visible = mController != null;
         state.label = mContext.getString(R.string.quick_settings_hotspot_label);
-        state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_hotspot);
+        state.iconId = R.drawable.ic_qs_hotspot_off;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 176e05c..c5ad9e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -31,7 +31,6 @@
     public LocationTile(Host host) {
         super(host);
         mController = host.getLocationController();
-        mController.addSettingsChangedCallback(mCallback);
     }
 
     @Override
@@ -39,8 +38,13 @@
         return new BooleanState();
     }
 
-    public void dispose() {
-        mController.removeSettingsChangedCallback(mCallback);
+    @Override
+    public void setListening(boolean listening) {
+        if (listening) {
+            mController.addSettingsChangedCallback(mCallback);
+        } else {
+            mController.removeSettingsChangedCallback(mCallback);
+        }
     }
 
     @Override
@@ -61,8 +65,8 @@
         if (state.value != locationEnabled) {
             state.value = locationEnabled;
             final AnimationDrawable d = (AnimationDrawable) mContext.getDrawable(locationEnabled
-                    ? R.drawable.ic_location_on_anim
-                    : R.drawable.ic_location_off_anim);
+                    ? R.drawable.ic_qs_location_on
+                    : R.drawable.ic_qs_location_off);
             state.icon = d;
             mUiHandler.post(new Runnable() {
                 @Override
@@ -71,15 +75,14 @@
                 }
             });
         }
-        //state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_location);
         if (locationEnabled) {
-            if (state.icon == null) state.iconId = R.drawable.ic_location_24_01;
+            if (state.icon == null) state.iconId = R.drawable.ic_qs_location_01;
             state.label = mContext.getString(R.string.quick_settings_location_label);
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_location,
                     mContext.getString(R.string.accessibility_desc_on));
         } else {
-            if (state.icon == null) state.iconId = R.drawable.ic_location_24_11;
+            if (state.icon == null) state.iconId = R.drawable.ic_qs_location_11;
             state.label = mContext.getString(R.string.quick_settings_location_off_label);
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_location,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java
index 36a579c..c5e9b52 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RingerModeTile.java
@@ -33,8 +33,6 @@
     public RingerModeTile(Host host) {
         super(host);
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        final IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
-        mContext.registerReceiver(mReceiver, filter);
     }
 
     @Override
@@ -43,8 +41,13 @@
     }
 
     @Override
-    public void dispose() {
-        mContext.unregisterReceiver(mReceiver);
+    public void setListening(boolean listening) {
+        if (listening) {
+            final IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
+            mContext.registerReceiver(mReceiver, filter);
+        } else {
+            mContext.unregisterReceiver(mReceiver);
+        }
     }
 
     @Override
@@ -64,13 +67,13 @@
         state.visible = true;
         state.value = ringerMode;
         if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
-            state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_ringer_vibrate);
+            state.iconId = R.drawable.ic_qs_ringer_vibrate;
             state.label = "Vibrate";
         } else if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
-            state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_ringer_silent);
+            state.iconId = R.drawable.ic_qs_ringer_silent;
             state.label = "Silent";
         } else {
-            state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_ringer_audible);
+            state.iconId = R.drawable.ic_qs_ringer_audible;
             state.label = "Audible";
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index d075299..1b0967b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -33,8 +33,6 @@
     public RotationLockTile(Host host) {
         super(host);
         mController = host.getRotationLockController();
-        if (mController == null) return;
-        mController.addRotationLockControllerCallback(mCallback);
     }
 
     @Override
@@ -42,9 +40,13 @@
         return new BooleanState();
     }
 
-    public void dispose() {
+    public void setListening(boolean listening) {
         if (mController == null) return;
-        mController.removeRotationLockControllerCallback(mCallback);
+        if (listening) {
+            mController.addRotationLockControllerCallback(mCallback);
+        } else {
+            mController.removeRotationLockControllerCallback(mCallback);
+        }
     }
 
     @Override
@@ -61,8 +63,8 @@
         if (state.value != rotationLocked) {
             state.value = rotationLocked;
             final AnimationDrawable d = (AnimationDrawable) mContext.getDrawable(rotationLocked
-                    ? R.drawable.ic_rotate_locked_anim
-                    : R.drawable.ic_rotate_unlocked_anim);
+                    ? R.drawable.ic_qs_rotation_locked
+                    : R.drawable.ic_qs_rotation_unlocked);
             state.icon = d;
             mUiHandler.post(new Runnable() {
                 @Override
@@ -80,12 +82,12 @@
                     : R.string.quick_settings_rotation_locked_label;
             state.label = mContext.getString(label);
             if (state.icon == null) {
-                state.icon = mContext.getDrawable(R.drawable.ic_rotate_24_15);
+                state.icon = mContext.getDrawable(R.drawable.ic_qs_rotation_15);
             }
         } else {
             state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
             if (state.icon == null) {
-                state.icon = mContext.getDrawable(R.drawable.ic_rotate_24_01);
+                state.icon = mContext.getDrawable(R.drawable.ic_qs_rotation_01);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index e08a6fa..ef7fb89 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.provider.Settings;
+import android.util.Log;
 
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
@@ -37,7 +38,11 @@
     public WifiTile(Host host) {
         super(host);
         mController = host.getNetworkController();
-        mController.addNetworkSignalChangedCallback(mCallback);
+    }
+
+    @Override
+    public boolean supportsDualTargets() {
+        return true;
     }
 
     @Override
@@ -46,8 +51,12 @@
     }
 
     @Override
-    public void dispose() {
-        mController.removeNetworkSignalChangedCallback(mCallback);
+    public void setListening(boolean listening) {
+        if (listening) {
+            mController.addNetworkSignalChangedCallback(mCallback);
+        } else {
+            mController.removeNetworkSignalChangedCallback(mCallback);
+        }
     }
 
     @Override
@@ -67,8 +76,9 @@
 
     @Override
     protected void handleUpdateState(SignalState state, Object arg) {
-        if (arg == null) return;
         state.visible = true;
+        if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
+        if (arg == null) return;
         CallbackInfo cb = (CallbackInfo) arg;
 
         boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
@@ -114,6 +124,18 @@
         boolean activityIn;
         boolean activityOut;
         String wifiSignalContentDescription;
+
+        @Override
+        public String toString() {
+            return new StringBuilder("CallbackInfo[")
+                .append("enabled=").append(enabled)
+                .append(",wifiSignalIconId=").append(wifiSignalIconId)
+                .append(",enabledDesc=").append(enabledDesc)
+                .append(",activityIn=").append(activityIn)
+                .append(",activityOut=").append(activityOut)
+                .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
+                .append(']').toString();
+        }
     }
 
     private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() {
@@ -121,6 +143,7 @@
         public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
                 boolean activityIn, boolean activityOut,
                 String wifiSignalContentDescriptionId, String description) {
+            if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
             final CallbackInfo info = new CallbackInfo();
             info.enabled = enabled;
             info.wifiSignalIconId = wifiSignalIconId;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java
index dceb856..2edefe7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeDetail.java
@@ -32,6 +32,7 @@
 import android.widget.ArrayAdapter;
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.RadioButton;
 import android.widget.RelativeLayout;
@@ -39,7 +40,6 @@
 import android.widget.TextView;
 
 import com.android.systemui.R;
-import com.android.systemui.qs.QSImageView;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.ZenModeController;
 
@@ -72,9 +72,7 @@
         mContext = getContext();
         mController = mHost.getZenModeController();
 
-        final QSImageView close = (QSImageView) findViewById(android.R.id.button1);
-        close.setImageDrawable(mHost.getVectorDrawable(R.drawable.ic_qs_close));
-        close.setEnabledVersion(true);
+        final ImageView close = (ImageView) findViewById(android.R.id.button1);
         close.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -239,9 +237,7 @@
             title.setText(condition.summary);
             title.setEnabled(enabled);
             title.setAlpha(enabled ? 1 : .5f);
-            final QSImageView button1 = (QSImageView) row.findViewById(android.R.id.button1);
-            button1.setImageDrawable(mHost.getVectorDrawable(R.drawable.ic_qs_minus));
-            button1.setEnabledVersion(true);
+            final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
             button1.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
@@ -250,9 +246,7 @@
                 }
             });
 
-            final QSImageView button2 = (QSImageView) row.findViewById(android.R.id.button2);
-            button2.setImageDrawable(mHost.getVectorDrawable(R.drawable.ic_qs_plus));
-            button2.setEnabledVersion(true);
+            final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
             button2.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java
index 83918e8..bfa9c19 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ZenModeTile.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles;
 
 import android.content.Context;
+import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -33,7 +34,6 @@
     public ZenModeTile(Host host) {
         super(host);
         mController = host.getZenModeController();
-        mController.addCallback(mCallback);
     }
 
     @Override
@@ -51,8 +51,12 @@
     }
 
     @Override
-    public void dispose() {
-        mController.removeCallback(mCallback);
+    public void setListening(boolean listening) {
+        if (listening) {
+            mController.addCallback(mCallback);
+        } else {
+            mController.removeCallback(mCallback);
+        }
     }
 
     @Override
@@ -69,14 +73,14 @@
         final boolean zen = arg instanceof Boolean ? (Boolean)arg : mController.isZen();
         state.value = zen;
         state.visible = true;
-        state.iconId = R.drawable.stat_sys_zen_limited;
-        state.icon = mHost.getVectorDrawable(R.drawable.ic_qs_zen);
+        state.iconId = zen ? R.drawable.ic_qs_zen_on : R.drawable.ic_qs_zen_off;
         state.label = mContext.getString(R.string.zen_mode_title);
     }
 
     private final ZenModeController.Callback mCallback = new ZenModeController.Callback() {
         @Override
         public void onZenChanged(boolean zen) {
+            if (DEBUG) Log.d(TAG, "onZenChanged " + zen);
             refreshState(zen);
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
index ae18aa8..00c43e8 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -27,7 +27,6 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -44,14 +43,12 @@
     private static final boolean DEBUG = true;
 
     // Which recents to use
-    boolean mUseAlternateRecents;
+    boolean mUseAlternateRecents = true;
     AlternateRecentsComponent mAlternateRecents;
     boolean mBootCompleted = false;
 
     @Override
     public void start() {
-        Configuration config = mContext.getResources().getConfiguration();
-        mUseAlternateRecents = (config.smallestScreenWidthDp < 600);
         if (mUseAlternateRecents) {
             if (mAlternateRecents == null) {
                 mAlternateRecents = new AlternateRecentsComponent(mContext);
@@ -68,10 +65,30 @@
     }
 
     @Override
+    public void showRecents(boolean triggeredFromAltTab, View statusBarView) {
+        if (mUseAlternateRecents) {
+            mAlternateRecents.onShowRecents(triggeredFromAltTab, statusBarView);
+        }
+    }
+
+    @Override
+    public void hideRecents() {
+        if (mUseAlternateRecents) {
+            mAlternateRecents.onHideRecents();
+        } else {
+            Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
+            intent.setPackage("com.android.systemui");
+            sendBroadcastSafely(intent);
+
+            RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
+        }
+    }
+
+    @Override
     public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
         if (mUseAlternateRecents) {
             // Launch the alternate recents if required
-            mAlternateRecents.onToggleRecents(display, layoutDirection, statusBarView);
+            mAlternateRecents.onToggleRecents(statusBarView);
             return;
         }
 
@@ -224,7 +241,7 @@
     }
 
     @Override
-    public void preloadRecentTasksList() {
+    public void preloadRecents() {
         if (mUseAlternateRecents) {
             mAlternateRecents.onPreloadRecents();
         } else {
@@ -238,7 +255,7 @@
     }
 
     @Override
-    public void cancelPreloadingRecentTasksList() {
+    public void cancelPreloadingRecents() {
         if (mUseAlternateRecents) {
             mAlternateRecents.onCancelPreloadingRecents();
         } else {
@@ -251,19 +268,6 @@
         }
     }
 
-    @Override
-    public void closeRecents() {
-        if (mUseAlternateRecents) {
-            mAlternateRecents.onCloseRecents();
-        } else {
-            Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
-            intent.setPackage("com.android.systemui");
-            sendBroadcastSafely(intent);
-
-            RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
-        }
-    }
-
     /**
      * Send broadcast only if BOOT_COMPLETED
      */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 19a1b11..ec50bfa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -44,9 +44,9 @@
 import android.view.WindowManager;
 import com.android.systemui.R;
 
-import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /** A proxy implementation for the recents component */
 public class AlternateRecentsComponent {
@@ -72,7 +72,7 @@
                 // If we had the update the animation rects as a result of onServiceConnected, then
                 // we check for whether we need to toggle the recents here.
                 if (mToggleRecentsUponServiceBound) {
-                    startAlternateRecentsActivity();
+                    startRecentsActivity();
                     mToggleRecentsUponServiceBound = false;
                 }
             }
@@ -90,9 +90,9 @@
             mServiceIsBound = true;
 
             if (hasValidTaskRects()) {
-                // Toggle recents if this new service connection was triggered by hitting recents
+                // Start recents if this new service connection was triggered by hitting recents
                 if (mToggleRecentsUponServiceBound) {
-                    startAlternateRecentsActivity();
+                    startRecentsActivity();
                     mToggleRecentsUponServiceBound = false;
                 }
             } else {
@@ -114,10 +114,12 @@
     final public static int MSG_UPDATE_TASK_THUMBNAIL = 1;
     final public static int MSG_PRELOAD_TASKS = 2;
     final public static int MSG_CANCEL_PRELOAD_TASKS = 3;
-    final public static int MSG_CLOSE_RECENTS = 4;
-    final public static int MSG_TOGGLE_RECENTS = 5;
+    final public static int MSG_SHOW_RECENTS = 4;
+    final public static int MSG_HIDE_RECENTS = 5;
+    final public static int MSG_TOGGLE_RECENTS = 6;
 
     final public static String EXTRA_ANIMATING_WITH_THUMBNAIL = "recents.animatingWithThumbnail";
+    final public static String EXTRA_FROM_ALT_TAB = "recents.triggeredFromAltTab";
     final public static String KEY_CONFIGURATION_DATA = "recents.data.updateForConfiguration";
     final public static String KEY_WINDOW_RECT = "recents.windowRect";
     final public static String KEY_SYSTEM_INSETS = "recents.systemInsets";
@@ -142,7 +144,10 @@
     boolean mToggleRecentsUponServiceBound;
     RecentsServiceConnection mConnection = new RecentsServiceConnection();
 
+    // Variables to keep track of if we need to start recents after binding
     View mStatusBarView;
+    boolean mTriggeredFromAltTab;
+
     Rect mSingleCountFirstTaskRect = new Rect();
     Rect mMultipleCountFirstTaskRect = new Rect();
     long mLastToggleTime;
@@ -160,15 +165,11 @@
         bindToRecentsService(false);
     }
 
-    /** Toggles the alternate recents activity */
-    public void onToggleRecents(Display display, int layoutDirection, View statusBarView) {
-        Console.logStartTracingTime(Constants.Log.App.TimeRecentsStartup,
-                Constants.Log.App.TimeRecentsStartupKey);
-        Console.logStartTracingTime(Constants.Log.App.TimeRecentsLaunchTask,
-                Constants.Log.App.TimeRecentsLaunchKey);
-        Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|toggleRecents]",
-                "serviceIsBound: " + mServiceIsBound);
+    /** Shows the recents */
+    public void onShowRecents(boolean triggeredFromAltTab, View statusBarView) {
+        Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|showRecents]");
         mStatusBarView = statusBarView;
+        mTriggeredFromAltTab = triggeredFromAltTab;
         if (!mServiceIsBound) {
             // Try to create a long-running connection to the recents service before toggling
             // recents
@@ -177,7 +178,47 @@
         }
 
         try {
-            startAlternateRecentsActivity();
+            startRecentsActivity();
+        } catch (ActivityNotFoundException e) {
+            Console.logRawError("Failed to launch RecentAppsIntent", e);
+        }
+    }
+
+    /** Hides the recents */
+    public void onHideRecents() {
+        Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|hideRecents]");
+        if (mServiceIsBound) {
+            // Notify recents to close it
+            try {
+                Bundle data = new Bundle();
+                Message msg = Message.obtain(null, MSG_HIDE_RECENTS, 0, 0);
+                msg.setData(data);
+                mService.send(msg);
+            } catch (RemoteException re) {
+                re.printStackTrace();
+            }
+        }
+    }
+
+    /** Toggles the alternate recents activity */
+    public void onToggleRecents(View statusBarView) {
+        Console.logStartTracingTime(Constants.Log.App.TimeRecentsStartup,
+                Constants.Log.App.TimeRecentsStartupKey);
+        Console.logStartTracingTime(Constants.Log.App.TimeRecentsLaunchTask,
+                Constants.Log.App.TimeRecentsLaunchKey);
+        Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|toggleRecents]",
+                "serviceIsBound: " + mServiceIsBound);
+        mStatusBarView = statusBarView;
+        mTriggeredFromAltTab = false;
+        if (!mServiceIsBound) {
+            // Try to create a long-running connection to the recents service before toggling
+            // recents
+            bindToRecentsService(true);
+            return;
+        }
+
+        try {
+            toggleRecentsActivity();
         } catch (ActivityNotFoundException e) {
             Console.logRawError("Failed to launch RecentAppsIntent", e);
         }
@@ -191,21 +232,6 @@
         // Do nothing
     }
 
-    public void onCloseRecents() {
-        Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|closeRecents]");
-        if (mServiceIsBound) {
-            // Try and update the recents configuration
-            try {
-                Bundle data = new Bundle();
-                Message msg = Message.obtain(null, MSG_CLOSE_RECENTS, 0, 0);
-                msg.setData(data);
-                mService.send(msg);
-            } catch (RemoteException re) {
-                re.printStackTrace();
-            }
-        }
-    }
-
     public void onConfigurationChanged(Configuration newConfig) {
         updateAnimationRects();
     }
@@ -355,8 +381,32 @@
                 taskRect.left, taskRect.top, null);
     }
 
-    /** Starts the recents activity */
-    void startAlternateRecentsActivity() {
+    /** Returns whether the recents is currently running */
+    boolean isRecentsTopMost(AtomicBoolean isHomeTopMost) {
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RunningTaskInfo> tasks = ssp.getRunningTasks(1);
+        if (!tasks.isEmpty()) {
+            ActivityManager.RunningTaskInfo topTask = tasks.get(0);
+            ComponentName topActivity = topTask.topActivity;
+
+            // Check if the front most activity is recents
+            if (topActivity.getPackageName().equals(sRecentsPackage) &&
+                    topActivity.getClassName().equals(sRecentsActivity)) {
+                if (isHomeTopMost != null) {
+                    isHomeTopMost.set(false);
+                }
+                return true;
+            }
+
+            if (isHomeTopMost != null) {
+                isHomeTopMost.set(ssp.isInHomeStack(topTask.id));
+            }
+        }
+        return false;
+    }
+
+    /** Toggles the recents activity */
+    void toggleRecentsActivity() {
         // If the user has toggled it too quickly, then just eat up the event here (it's better than
         // showing a janky screenshot).
         // NOTE: Ideally, the screenshot mechanism would take the window transform into account
@@ -366,43 +416,47 @@
 
         // If Recents is the front most activity, then we should just communicate with it directly
         // to launch the first task or dismiss itself
-        SystemServicesProxy ssp = mSystemServicesProxy;
-        List<ActivityManager.RunningTaskInfo> tasks = ssp.getRunningTasks(1);
-        boolean isTopTaskHome = false;
-        if (!tasks.isEmpty()) {
-            ActivityManager.RunningTaskInfo topTask = tasks.get(0);
-            ComponentName topActivity = topTask.topActivity;
+        AtomicBoolean isTopTaskHome = new AtomicBoolean();
+        if (isRecentsTopMost(isTopTaskHome)) {
+            // Notify recents to close itself
+            try {
+                Bundle data = new Bundle();
+                Message msg = Message.obtain(null, MSG_TOGGLE_RECENTS, 0, 0);
+                msg.setData(data);
+                mService.send(msg);
 
-            // Check if the front most activity is recents
-            if (topActivity.getPackageName().equals(sRecentsPackage) &&
-                    topActivity.getClassName().equals(sRecentsActivity)) {
-                // Notify Recents to toggle itself
-                try {
-                    Bundle data = new Bundle();
-                    Message msg = Message.obtain(null, MSG_TOGGLE_RECENTS, 0, 0);
-                    msg.setData(data);
-                    mService.send(msg);
-
-                    // Time this path
-                    Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
-                            Constants.Log.App.TimeRecentsStartupKey, "sendToggleRecents");
-                    Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
-                            Constants.Log.App.TimeRecentsLaunchKey, "sendToggleRecents");
-                } catch (RemoteException re) {
-                    re.printStackTrace();
-                }
-                mLastToggleTime = System.currentTimeMillis();
-                return;
+                // Time this path
+                Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+                        Constants.Log.App.TimeRecentsStartupKey, "sendToggleRecents");
+                Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
+                        Constants.Log.App.TimeRecentsLaunchKey, "sendToggleRecents");
+            } catch (RemoteException re) {
+                re.printStackTrace();
             }
-
-            // Determine whether the top task is currently home
-            isTopTaskHome = ssp.isInHomeStack(topTask.id);
+            mLastToggleTime = System.currentTimeMillis();
+            return;
+        } else {
+            // Otherwise, start the recents activity
+            startRecentsActivity(isTopTaskHome.get());
         }
+    }
 
-        // Otherwise, Recents is not the front-most activity and we should animate into it.  If
+    /** Starts the recents activity if it is not already running */
+    void startRecentsActivity() {
+        // Check if the top task is in the home stack, and start the recents activity
+        AtomicBoolean isTopTaskHome = new AtomicBoolean();
+        if (!isRecentsTopMost(isTopTaskHome)) {
+            startRecentsActivity(isTopTaskHome.get());
+        }
+    }
+
+    /** Starts the recents activity */
+    void startRecentsActivity(boolean isTopTaskHome) {
+        // If Recents is not the front-most activity and we should animate into it.  If
         // the activity at the root of the top task stack in the home stack, then we just do a
         // simple transition.  Otherwise, we animate to the rects defined by the Recents service,
         // which can differ depending on the number of items in the list.
+        SystemServicesProxy ssp = mSystemServicesProxy;
         List<ActivityManager.RecentTaskInfo> recentTasks =
                 ssp.getRecentTasks(2, UserHandle.CURRENT.getIdentifier());
         Rect taskRect = hasMultipleRecentsTask(recentTasks) ? mMultipleCountFirstTaskRect :
@@ -422,9 +476,6 @@
         }
 
         // If there is no thumbnail transition, then just use a generic transition
-        // XXX: This should be different between home and from a recents-excluded app, perhaps the
-        //      recents-excluded app should still show up in recents, when the app is in the
-        //      foreground
         if (!useThumbnailTransition) {
             ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
                     R.anim.recents_from_launcher_enter,
@@ -444,6 +495,7 @@
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
         intent.putExtra(EXTRA_ANIMATING_WITH_THUMBNAIL, animatingWithThumbnail);
+        intent.putExtra(EXTRA_FROM_ALT_TAB, mTriggeredFromAltTab);
         if (opts != null) {
             mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
                     UserHandle.USER_CURRENT));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 90998da..9390b0d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -69,6 +69,7 @@
             public static final boolean TouchEvents = false;
             public static final boolean MeasureAndLayout = false;
             public static final boolean HwLayers = false;
+            public static final boolean Focus = false;
         }
 
         public static class TaskStack {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b74f6ac..325e4b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -28,6 +28,7 @@
 import android.content.IntentFilter;
 import android.os.Bundle;
 import android.util.Pair;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
@@ -81,7 +82,10 @@
             String action = intent.getAction();
             Console.log(Constants.Log.App.SystemUIHandshake,
                     "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
-            if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
+            if (action.equals(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY)) {
+                // Dismiss recents, launching the focused task
+                dismissRecentsIfVisible();
+            } else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
                 // Try and unfilter and filtered stacks
                 if (!mRecentsView.unfilterFilteredStacks()) {
                     // If there are no filtered stacks, dismiss recents and launch the first task
@@ -105,6 +109,8 @@
         RecentsConfiguration config = RecentsConfiguration.getInstance();
         config.launchedWithThumbnailAnimation = launchIntent.getBooleanExtra(
                 AlternateRecentsComponent.EXTRA_ANIMATING_WITH_THUMBNAIL, false);
+        config.launchedFromAltTab = launchIntent.getBooleanExtra(
+                AlternateRecentsComponent.EXTRA_FROM_ALT_TAB, false);
 
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
@@ -184,7 +190,7 @@
             int appWidgetId = config.searchBarAppWidgetId;
             if (appWidgetId >= 0) {
                 Console.log(Constants.Log.App.SystemUIHandshake,
-                        "[RecentsActivity|onCreate|addSearchAppWidgetView]",
+                "[RecentsActivity|onCreate|addSearchAppWidgetView]",
                         "Id: " + appWidgetId,
                         Console.AnsiBlue);
                 mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
@@ -205,8 +211,10 @@
     /** Dismisses recents if we are already visible and the intent is to toggle the recents view */
     boolean dismissRecentsIfVisible() {
         if (mVisible) {
-            if (!mRecentsView.launchFirstTask()) {
-                finish();
+            if (!mRecentsView.launchFocusedTask()) {
+                if (!mRecentsView.launchFirstTask()) {
+                    finish();
+                }
             }
             return true;
         }
@@ -303,6 +311,7 @@
 
         // Register the broadcast receiver to handle messages from our service
         IntentFilter filter = new IntentFilter();
+        filter.addAction(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY);
         filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
         registerReceiver(mServiceBroadcastReceiver, filter);
 
@@ -362,6 +371,18 @@
     }
 
     @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_TAB) {
+            // Focus the next task in the stack
+            final boolean backward = event.isShiftPressed();
+            mRecentsView.focusNextTask(!backward);
+            return true;
+        }
+
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
     public void onBackPressed() {
         boolean interceptedByInfoPanelClose = false;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 9afc1cb..8399551 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -65,6 +65,7 @@
     public int taskBarViewLightTextColor;
     public int taskBarViewDarkTextColor;
 
+    public boolean launchedFromAltTab;
     public boolean launchedWithThumbnailAnimation;
 
     /** Private constructor */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 837cb34..601b382 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -106,8 +106,11 @@
             } catch (RemoteException re) {
                 re.printStackTrace();
             }
-        } else if (msg.what == AlternateRecentsComponent.MSG_CLOSE_RECENTS) {
-            // Do nothing
+        } else if (msg.what == AlternateRecentsComponent.MSG_HIDE_RECENTS) {
+            // Send a broadcast to hide recents
+            Intent intent = new Intent(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY);
+            intent.setPackage(context.getPackageName());
+            context.sendBroadcast(intent);
         } else if (msg.what == AlternateRecentsComponent.MSG_TOGGLE_RECENTS) {
             // Send a broadcast to toggle recents
             Intent intent = new Intent(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
@@ -125,6 +128,7 @@
 
 /* Service */
 public class RecentsService extends Service {
+    final static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
     final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
 
     Messenger mSystemUIMessenger = new Messenger(new SystemUIMessageHandler(this));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index a6d7e67..2821052 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -94,6 +94,34 @@
         }
     }
 
+    /** Launches the focused task from the first stack if possible */
+    public boolean launchFocusedTask() {
+        // Get the first stack view
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child instanceof TaskStackView) {
+                TaskStackView stackView = (TaskStackView) child;
+                TaskStack stack = stackView.mStack;
+                // Iterate the stack views and try and find the focused task
+                int taskCount = stackView.getChildCount();
+                for (int j = 0; j < taskCount; j++) {
+                    TaskView tv = (TaskView) stackView.getChildAt(j);
+                    Task task = tv.getTask();
+                    if (tv.isFocusedTask()) {
+                        Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
+                                "Found focused Task");
+                        onTaskLaunched(stackView, tv, stack, task);
+                        return true;
+                    }
+                }
+            }
+        }
+        Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
+                "No Tasks focused");
+        return false;
+    }
+
     /** Launches the first task from the first stack if possible */
     public boolean launchFirstTask() {
         // Get the first stack view
@@ -234,6 +262,24 @@
         }
     }
 
+    /** Focuses the next task in the first stack view */
+    public void focusNextTask(boolean forward) {
+        // Get the first stack view
+        TaskStackView stackView = null;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child instanceof TaskStackView) {
+                stackView = (TaskStackView) child;
+                break;
+            }
+        }
+
+        if (stackView != null) {
+            stackView.focusNextTask(forward);
+        }
+    }
+
     @Override
     protected void dispatchDraw(Canvas canvas) {
         Console.log(Constants.Log.UI.Draw, "[RecentsView|dispatchDraw]", "",
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index b64225e..37c3c35 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -80,6 +80,7 @@
     int mMaxScroll;
     int mStashedScroll;
     int mLastInfoPaneStackScroll;
+    int mFocusedTaskIndex = -1;
     OverScroller mScroller;
     ObjectAnimator mScrollAnimator;
 
@@ -306,6 +307,15 @@
         mStackScroll = value;
     }
 
+    /**
+     * Returns the scroll to such that the task transform at that index will have t=0. (If the scroll
+     * is not bounded)
+     */
+    int getStackScrollForTaskIndex(int i) {
+        int taskHeight = mTaskRect.height();
+        return (int) (i * Constants.Values.TaskStackView.StackOverlapPct * taskHeight);
+    }
+
     /** Gets the current stack scroll */
     public int getStackScroll() {
         return mStackScroll;
@@ -460,6 +470,64 @@
         return false;
     }
 
+    /** Focuses the task at the specified index in the stack */
+    void focusTask(int taskIndex, boolean scrollToNewPosition) {
+        Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "" + taskIndex);
+        if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
+            mFocusedTaskIndex = taskIndex;
+
+            // Focus the view if possible, otherwise, focus the view after we scroll into position
+            Task t = mStack.getTasks().get(taskIndex);
+            TaskView tv = getChildViewForTask(t);
+            Runnable postScrollRunnable = null;
+            if (tv != null) {
+                tv.setFocusedTask();
+                Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "Requesting focus");
+            } else {
+                postScrollRunnable = new Runnable() {
+                    @Override
+                    public void run() {
+                        Task t = mStack.getTasks().get(mFocusedTaskIndex);
+                        TaskView tv = getChildViewForTask(t);
+                        if (tv != null) {
+                            tv.setFocusedTask();
+                            Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]",
+                                    "Requesting focus after scroll animation");
+                        }
+                    }
+                };
+            }
+
+            if (scrollToNewPosition) {
+                // Scroll the view into position
+                int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll,
+                        getStackScrollForTaskIndex(taskIndex)));
+
+                animateScroll(getStackScroll(), newScroll, postScrollRunnable);
+            } else {
+                if (postScrollRunnable != null) {
+                    postScrollRunnable.run();
+                }
+            }
+        }
+    }
+
+    /** Focuses the next task in the stack */
+    void focusNextTask(boolean forward) {
+        Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusNextTask]", "" + mFocusedTaskIndex);
+
+        // Find the next index to focus
+        int numTasks = mStack.getTaskCount();
+        if (mFocusedTaskIndex < 0) {
+            mFocusedTaskIndex = numTasks - 1;
+        }
+        if (0 <= mFocusedTaskIndex && mFocusedTaskIndex < numTasks) {
+            mFocusedTaskIndex = Math.max(0, Math.min(numTasks - 1,
+                    mFocusedTaskIndex + (forward ? -1 : 1)));
+        }
+        focusTask(mFocusedTaskIndex, true);
+    }
+
     /** Enables the hw layers and increments the hw layer requirement ref count */
     void addHwLayersRefCount(String reason) {
         Console.log(Constants.Log.UI.HwLayers,
@@ -631,6 +699,11 @@
             requestSynchronizeStackViewsWithModel();
             synchronizeStackViewsWithModel();
 
+            // Update the focused task index to be the next item to the top task
+            if (config.launchedFromAltTab) {
+                focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
+            }
+
             // Animate the task bar of the first task view
             if (config.launchedWithThumbnailAnimation) {
                 TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 5fad629..ffcb82b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -18,6 +18,7 @@
 
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Outline;
@@ -57,6 +58,7 @@
     Task mTask;
     boolean mTaskDataLoaded;
     boolean mTaskInfoPaneVisible;
+    boolean mIsFocused;
     Point mLastTouchDown = new Point();
     Path mRoundedRectClipPath = new Path();
 
@@ -367,6 +369,34 @@
         }
     }
 
+    /**
+     * Sets the focused task explicitly. We need a separate flag because requestFocus() won't happen
+     * if the view is not currently visible, or we are in touch state (where we still want to keep
+     * track of focus).
+     */
+    public void setFocusedTask() {
+        mIsFocused = true;
+        requestFocus();
+    }
+
+    /**
+     * Updates the explicitly focused state when the view focus changes.
+     */
+    @Override
+    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+        if (!gainFocus) {
+            mIsFocused = false;
+        }
+    }
+
+    /**
+     * Returns whether we have explicitly been focused.
+     */
+    public boolean isFocusedTask() {
+        return mIsFocused || isFocused();
+    }
+
     /**** TaskCallbacks Implementation ****/
 
     /** Binds this task view to the task */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index c1228d9..7918dec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -87,8 +87,9 @@
     public static final boolean DEBUG = false;
     public static final boolean MULTIUSER_DEBUG = false;
 
-    protected static final int MSG_TOGGLE_RECENTS_PANEL = 1020;
-    protected static final int MSG_CLOSE_RECENTS_PANEL = 1021;
+    protected static final int MSG_SHOW_RECENT_APPS = 1019;
+    protected static final int MSG_HIDE_RECENT_APPS = 1020;
+    protected static final int MSG_TOGGLE_RECENTS_APPS = 1021;
     protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
     protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
     protected static final int MSG_OPEN_SEARCH_PANEL = 1024;
@@ -496,8 +497,22 @@
     }
 
     @Override
+    public void showRecentApps(boolean triggeredFromAltTab) {
+        int msg = MSG_SHOW_RECENT_APPS;
+        mHandler.removeMessages(msg);
+        mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0, 0).sendToTarget();
+    }
+
+    @Override
+    public void hideRecentApps() {
+        int msg = MSG_HIDE_RECENT_APPS;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
+    @Override
     public void toggleRecentApps() {
-        int msg = MSG_TOGGLE_RECENTS_PANEL;
+        int msg = MSG_TOGGLE_RECENTS_APPS;
         mHandler.removeMessages(msg);
         mHandler.sendEmptyMessage(msg);
     }
@@ -580,12 +595,12 @@
         public boolean onTouch(View v, MotionEvent event) {
             int action = event.getAction() & MotionEvent.ACTION_MASK;
             if (action == MotionEvent.ACTION_DOWN) {
-                preloadRecentTasksList();
+                preloadRecents();
             } else if (action == MotionEvent.ACTION_CANCEL) {
-                cancelPreloadingRecentTasksList();
+                cancelPreloadingRecents();
             } else if (action == MotionEvent.ACTION_UP) {
                 if (!v.isPressed()) {
-                    cancelPreloadingRecentTasksList();
+                    cancelPreloadingRecents();
                 }
 
             }
@@ -593,28 +608,38 @@
         }
     };
 
-    protected void toggleRecentsActivity() {
+    /** Proxy for RecentsComponent */
+
+    protected void showRecents(boolean triggeredFromAltTab) {
+        if (mRecents != null) {
+            sendCloseSystemWindows(mContext, SYSTEM_DIALOG_REASON_RECENT_APPS);
+            mRecents.showRecents(triggeredFromAltTab, getStatusBarView());
+        }
+    }
+
+    protected void hideRecents() {
+        if (mRecents != null) {
+            sendCloseSystemWindows(mContext, SYSTEM_DIALOG_REASON_RECENT_APPS);
+            mRecents.hideRecents();
+        }
+    }
+
+    protected void toggleRecents() {
         if (mRecents != null) {
             sendCloseSystemWindows(mContext, SYSTEM_DIALOG_REASON_RECENT_APPS);
             mRecents.toggleRecents(mDisplay, mLayoutDirection, getStatusBarView());
         }
     }
 
-    protected void preloadRecentTasksList() {
+    protected void preloadRecents() {
         if (mRecents != null) {
-            mRecents.preloadRecentTasksList();
+            mRecents.preloadRecents();
         }
     }
 
-    protected void cancelPreloadingRecentTasksList() {
+    protected void cancelPreloadingRecents() {
         if (mRecents != null) {
-            mRecents.cancelPreloadingRecentTasksList();
-        }
-    }
-
-    protected void closeRecents() {
-        if (mRecents != null) {
-            mRecents.closeRecents();
+            mRecents.cancelPreloadingRecents();
         }
     }
 
@@ -655,17 +680,20 @@
         public void handleMessage(Message m) {
             Intent intent;
             switch (m.what) {
-             case MSG_TOGGLE_RECENTS_PANEL:
-                 toggleRecentsActivity();
+             case MSG_SHOW_RECENT_APPS:
+                 showRecents(m.arg1 > 0);
                  break;
-             case MSG_CLOSE_RECENTS_PANEL:
-                 closeRecents();
+             case MSG_HIDE_RECENT_APPS:
+                 hideRecents();
+                 break;
+             case MSG_TOGGLE_RECENTS_APPS:
+                 toggleRecents();
                  break;
              case MSG_PRELOAD_RECENT_APPS:
-                  preloadRecentTasksList();
+                  preloadRecents();
                   break;
              case MSG_CANCEL_PRELOAD_RECENT_APPS:
-                  cancelPreloadingRecentTasksList();
+                  cancelPreloadingRecents();
                   break;
              case MSG_OPEN_SEARCH_PANEL:
                  if (DEBUG) Log.d(TAG, "opening search panel");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 5362af5..ebab7fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -57,6 +57,8 @@
     private static final int MSG_PRELOAD_RECENT_APPS        = 14 << MSG_SHIFT;
     private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 15 << MSG_SHIFT;
     private static final int MSG_SET_WINDOW_STATE           = 16 << MSG_SHIFT;
+    private static final int MSG_SHOW_RECENT_APPS           = 17 << MSG_SHIFT;
+    private static final int MSG_HIDE_RECENT_APPS           = 18 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -96,11 +98,13 @@
         public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
                 boolean showImeSwitcher);
         public void setHardKeyboardStatus(boolean available, boolean enabled);
+        public void showRecentApps(boolean triggeredFromAltTab);
+        public void hideRecentApps();
         public void toggleRecentApps();
         public void preloadRecentApps();
+        public void cancelPreloadRecentApps();
         public void showSearchPanel();
         public void hideSearchPanel();
-        public void cancelPreloadRecentApps();
         public void setWindowState(int window, int state);
 
     }
@@ -211,6 +215,21 @@
         }
     }
 
+    public void showRecentApps(boolean triggeredFromAltTab) {
+        synchronized (mList) {
+            mHandler.removeMessages(MSG_SHOW_RECENT_APPS);
+            mHandler.obtainMessage(MSG_SHOW_RECENT_APPS,
+                    triggeredFromAltTab ? 1 : 0, 0, null).sendToTarget();
+        }
+    }
+
+    public void hideRecentApps() {
+        synchronized (mList) {
+            mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
+            mHandler.obtainMessage(MSG_HIDE_RECENT_APPS, 0, 0, null).sendToTarget();
+        }
+    }
+
     public void toggleRecentApps() {
         synchronized (mList) {
             mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
@@ -309,6 +328,12 @@
                 case MSG_SET_HARD_KEYBOARD_STATUS:
                     mCallbacks.setHardKeyboardStatus(msg.arg1 != 0, msg.arg2 != 0);
                     break;
+                case MSG_SHOW_RECENT_APPS:
+                    mCallbacks.showRecentApps(msg.arg1 != 0);
+                    break;
+                case MSG_HIDE_RECENT_APPS:
+                    mCallbacks.hideRecentApps();
+                    break;
                 case MSG_TOGGLE_RECENT_APPS:
                     mCallbacks.toggleRecentApps();
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
index 6401695..9c39002 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
@@ -89,7 +89,7 @@
             return;
         }
         final Notification n = new Notification.Builder(mContext)
-                .setSmallIcon(R.drawable.stat_sys_zen_limited)
+                .setSmallIcon(R.drawable.ic_qs_zen_on)
                 .setContentTitle(mContext.getResources().getQuantityString(
                         R.plurals.zen_mode_notification_title,
                         mIntercepted.size(), mIntercepted.size()))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 869edff..0a3fdef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -60,7 +60,8 @@
         } else if (mDemoMode && command.equals(COMMAND_STATUS)) {
             String volume = args.getString("volume");
             if (volume != null) {
-                int iconId = volume.equals("silent") ? R.drawable.stat_sys_ringer_silent
+                int iconId = volume.equals("zen") ? R.drawable.stat_sys_ringer_zen
+                        : volume.equals("silent") ? R.drawable.stat_sys_ringer_silent
                         : volume.equals("vibrate") ? R.drawable.stat_sys_ringer_vibrate
                         : 0;
                 updateSlot("volume", null, iconId);
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 a92061f..1072e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -223,8 +223,6 @@
     IconMerger mNotificationIcons;
     // [+>
     View mMoreIcon;
-    // mode indicator icon
-    ImageView mModeIcon;
 
     // expanded notifications
     NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -488,13 +486,14 @@
     @Override
     public void setZenMode(int mode) {
         super.setZenMode(mode);
-        if (mModeIcon == null) return;
         if (!isDeviceProvisioned()) return;
         final boolean zen = mode != Settings.Global.ZEN_MODE_OFF;
-        mModeIcon.setVisibility(zen ? View.VISIBLE : View.GONE);
         if (!zen) {
             mIntercepted.releaseIntercepted();
         }
+        if (mIconPolicy != null) {
+            mIconPolicy.setZenMode(zen);
+        }
     }
 
     @Override
@@ -618,8 +617,6 @@
         mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
         mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
         mNotificationIcons.setOverflowIndicator(mMoreIcon);
-        mModeIcon = (ImageView)mStatusBarView.findViewById(R.id.modeIcon);
-        mModeIcon.setImageResource(R.drawable.stat_sys_zen_limited);
         mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
         mTickerView = mStatusBarView.findViewById(R.id.ticker);
 
@@ -1396,8 +1393,8 @@
 
             if ((state & StatusBarManager.DISABLE_RECENT) != 0) {
                 // close recents if it's visible
-                mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
-                mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
+                mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
+                mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
             }
         }
 
@@ -1548,8 +1545,8 @@
         }
 
         if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
-            mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
-            mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
+            mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
+            mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
         }
 
         if ((flags & CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL) == 0) {
@@ -2565,13 +2562,13 @@
                 || (mDisabled & StatusBarManager.DISABLE_SEARCH) != 0;
     }
 
-    public void postStartSettingsActivity(final Intent intent) {
-        mHandler.post(new Runnable() {
+    public void postStartSettingsActivity(final Intent intent, int delay) {
+        mHandler.postDelayed(new Runnable() {
             @Override
             public void run() {
                 handleStartSettingsActivity(intent, true /*onlyProvisioned*/);
             }
-        });
+        }, delay);
     }
 
     private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
@@ -2587,7 +2584,7 @@
     }
 
     public void startSettingsActivity(String action) {
-        postStartSettingsActivity(new Intent(action));
+        postStartSettingsActivity(new Intent(action), 0);
     }
 
     private static class FastColorDrawable extends Drawable {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 194774d..b6f5ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -63,6 +63,9 @@
     // ringer volume
     private boolean mVolumeVisible;
 
+    // zen mode
+    private boolean mZen;
+
     // bluetooth device status
     private boolean mBluetoothEnabled = false;
 
@@ -152,6 +155,11 @@
         updateVolume();
     }
 
+    public void setZenMode(boolean zen) {
+        mZen = zen;
+        updateVolume();
+    }
+
     private final void updateAlarm(Intent intent) {
         boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
         mService.setIconVisibility("alarm_clock", alarmSet);
@@ -195,11 +203,15 @@
         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         final int ringerMode = audioManager.getRingerMode();
         final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
-                ringerMode == AudioManager.RINGER_MODE_VIBRATE;
+                ringerMode == AudioManager.RINGER_MODE_VIBRATE ||
+                mZen;
 
         final int iconId;
         String contentDescription = null;
-        if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
+        if (mZen) {
+            iconId = R.drawable.stat_sys_ringer_zen;
+            contentDescription = mContext.getString(R.string.zen_mode_title);
+        } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
             iconId = R.drawable.stat_sys_ringer_vibrate;
             contentDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 1fe3be5..7029898 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.drawable.VectorDrawable;
 import android.os.HandlerThread;
 import android.os.Looper;
 
@@ -113,7 +112,7 @@
 
     @Override
     public void startSettingsActivity(final Intent intent) {
-        mStatusBar.postStartSettingsActivity(intent);
+        mStatusBar.postStartSettingsActivity(intent, QSTile.FEEDBACK_START_DELAY);
     }
 
     @Override
@@ -137,11 +136,6 @@
     }
 
     @Override
-    public VectorDrawable getVectorDrawable(int resId) {
-        return (VectorDrawable) mContext.getDrawable(resId);
-    }
-
-    @Override
     public BluetoothController getBluetoothController() {
         return mBluetooth;
     }
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 2305445..36b063b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -86,6 +86,7 @@
                 (ImageView) findViewById(R.id.brightness_icon),
                 (ToggleSlider) findViewById(R.id.brightness_slider));
         loadDimens();
+        updateVisibilities();
     }
 
     private void loadDimens() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 1c7119f..5a19881 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -59,6 +59,7 @@
 
     public void addStateChangedCallback(BluetoothStateChangeCallback cb) {
         mChangeCallbacks.add(cb);
+        fireCallback(cb);
     }
 
     @Override
@@ -131,7 +132,11 @@
 
     private void fireCallbacks() {
         for (BluetoothStateChangeCallback cb : mChangeCallbacks) {
-            cb.onBluetoothStateChange(mEnabled);
+            fireCallback(cb);
         }
     }
+
+    private void fireCallback(BluetoothStateChangeCallback cb) {
+        cb.onBluetoothStateChange(mEnabled);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 33a85b1..bcd865c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -28,6 +28,10 @@
     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     private final MediaRouter mMediaRouter;
 
+    private boolean mEnabled;
+    private boolean mConnecting;
+    private String mConnectedRouteName;
+
     public CastControllerImpl(Context context) {
         mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
     }
@@ -35,6 +39,7 @@
     @Override
     public void addCallback(Callback callback) {
         mCallbacks.add(callback);
+        fireStateChanged(callback);
     }
 
     @Override
@@ -76,12 +81,23 @@
         if (connectedRoute != null) {
             connectedRouteName = connectedRoute.getName().toString();
         }
-        fireStateChanged(enabled, connecting, connectedRouteName);
+        synchronized(mCallbacks) {
+            mEnabled = enabled;
+            mConnecting = connecting;
+            mConnectedRouteName = connectedRouteName;
+        }
+        fireStateChanged();
     }
 
-    private void fireStateChanged(boolean enabled, boolean connecting, String connectedRouteName) {
+    private void fireStateChanged() {
         for (Callback callback : mCallbacks) {
-            callback.onStateChanged(enabled, connecting, connectedRouteName);
+            fireStateChanged(callback);
+        }
+    }
+
+    private void fireStateChanged(Callback callback) {
+        synchronized(mCallbacks) {
+            callback.onStateChanged(mEnabled, mConnecting, mConnectedRouteName);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Listenable.java
similarity index 82%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/policy/Listenable.java
index 158e9c1..4fa59fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Disposable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Listenable.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.policy;
 
-/** Common interface for items requiring manual cleanup. **/
-public interface Disposable {
-    void dispose();
+/** Common interface for components with an active listening state. **/
+public interface Listenable {
+    void setListening(boolean listening);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 9e5ad18..d5b2548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -92,6 +92,7 @@
      */
     public void addSettingsChangedCallback(LocationSettingsChangeCallback cb) {
         mSettingsChangeCallbacks.add(cb);
+        locationSettingsChanged(cb);
     }
 
     public void removeSettingsChangedCallback(LocationSettingsChangeCallback cb) {
@@ -204,6 +205,10 @@
         }
     }
 
+    private void locationSettingsChanged(LocationSettingsChangeCallback cb) {
+        cb.onLocationSettingsChanged(isLocationEnabled());
+    }
+
     @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
index 1eb678d..93c4691 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.policy;
 
-public interface RotationLockController extends Disposable {
+public interface RotationLockController extends Listenable {
     int getRotationLockOrientation();
     boolean isRotationLockAffordanceVisible();
     boolean isRotationLocked();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
index caa07ef..c3bcd94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
@@ -39,12 +39,12 @@
 
     public RotationLockControllerImpl(Context context) {
         mContext = context;
-        RotationPolicy.registerRotationPolicyListener(mContext,
-                mRotationPolicyListener, UserHandle.USER_ALL);
+        setListening(true);
     }
 
     public void addRotationLockControllerCallback(RotationLockControllerCallback callback) {
         mCallbacks.add(callback);
+        notifyChanged(callback);
     }
 
     public void removeRotationLockControllerCallback(RotationLockControllerCallback callback) {
@@ -68,14 +68,23 @@
     }
 
     @Override
-    public void dispose() {
-        RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
+    public void setListening(boolean listening) {
+        if (listening) {
+            RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener,
+                    UserHandle.USER_ALL);
+        } else {
+            RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
+        }
     }
 
     private void notifyChanged() {
         for (RotationLockControllerCallback callback : mCallbacks) {
-            callback.onRotationLockStateChanged(RotationPolicy.isRotationLocked(mContext),
-                    RotationPolicy.isRotationLockToggleVisible(mContext));
+            notifyChanged(callback);
         }
     }
+
+    private void notifyChanged(RotationLockControllerCallback callback) {
+        callback.onRotationLockStateChanged(RotationPolicy.isRotationLocked(mContext),
+                RotationPolicy.isRotationLockToggleVisible(mContext));
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index d760f78..adf2935 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -52,6 +52,7 @@
                 fireZenChanged(value != 0);
             }
         };
+        mSetting.setListening(true);
         mNoMan = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index e204cb2..2fea785 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -36,6 +36,7 @@
 import com.android.internal.widget.ActionBarContextView;
 import com.android.internal.widget.ActionBarOverlayLayout;
 import com.android.internal.widget.ActionBarView;
+import com.android.internal.widget.DecorContentParent;
 import com.android.internal.widget.SwipeDismissLayout;
 
 import android.app.ActivityManager;
@@ -147,7 +148,7 @@
 
     private TextView mTitleView;
 
-    private ActionBarView mActionBar;
+    private DecorContentParent mDecorContentParent;
     private ActionMenuPresenterCallback mActionMenuPresenterCallback;
     private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
 
@@ -441,8 +442,8 @@
     public void setTitle(CharSequence title) {
         if (mTitleView != null) {
             mTitleView.setText(title);
-        } else if (mActionBar != null) {
-            mActionBar.setWindowTitle(title);
+        } else if (mDecorContentParent != null) {
+            mDecorContentParent.setWindowTitle(title);
         }
         mTitle = title;
     }
@@ -489,10 +490,10 @@
         final boolean isActionBarMenu =
                 (st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR);
 
-        if (isActionBarMenu && mActionBar != null) {
+        if (isActionBarMenu && mDecorContentParent != null) {
             // Enforce ordering guarantees around events so that the action bar never
             // dispatches menu-related events before the panel is prepared.
-            mActionBar.setMenuPrepared();
+            mDecorContentParent.setMenuPrepared();
         }
 
         if (st.createdPanelView == null) {
@@ -504,11 +505,11 @@
                     }
                 }
 
-                if (isActionBarMenu && mActionBar != null) {
+                if (isActionBarMenu && mDecorContentParent != null) {
                     if (mActionMenuPresenterCallback == null) {
                         mActionMenuPresenterCallback = new ActionMenuPresenterCallback();
                     }
-                    mActionBar.setMenu(st.menu, mActionMenuPresenterCallback);
+                    mDecorContentParent.setMenu(st.menu, mActionMenuPresenterCallback);
                 }
 
                 // Call callback, and return if it doesn't want to display menu.
@@ -520,9 +521,9 @@
                     // Ditch the menu created above
                     st.setMenu(null);
 
-                    if (isActionBarMenu && mActionBar != null) {
+                    if (isActionBarMenu && mDecorContentParent != null) {
                         // Don't show it in the action bar either
-                        mActionBar.setMenu(null, mActionMenuPresenterCallback);
+                        mDecorContentParent.setMenu(null, mActionMenuPresenterCallback);
                     }
 
                     return false;
@@ -545,10 +546,10 @@
             }
 
             if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) {
-                if (isActionBarMenu && mActionBar != null) {
+                if (isActionBarMenu && mDecorContentParent != null) {
                     // The app didn't want to show the menu for now but it still exists.
                     // Clear it out of the action bar.
-                    mActionBar.setMenu(null, mActionMenuPresenterCallback);
+                    mDecorContentParent.setMenu(null, mActionMenuPresenterCallback);
                 }
                 st.menu.startDispatchingItemsChanged();
                 return false;
@@ -573,7 +574,7 @@
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         // Action bars handle their own menu state
-        if (mActionBar == null) {
+        if (mDecorContentParent == null) {
             PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
             if ((st != null) && (st.menu != null)) {
                 if (st.isOpen) {
@@ -625,12 +626,10 @@
 
     @Override
     public final void openPanel(int featureId, KeyEvent event) {
-        if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null &&
-                mActionBar.isOverflowReserved() &&
+        if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
+                mDecorContentParent.canShowOverflowMenu() &&
                 !ViewConfiguration.get(getContext()).hasPermanentMenuKey()) {
-            if (mActionBar.getVisibility() == View.VISIBLE) {
-                mActionBar.showOverflowMenu();
-            }
+            mDecorContentParent.showOverflowMenu();
         } else {
             openPanel(getPanelState(featureId, true), event);
         }
@@ -759,10 +758,10 @@
 
     @Override
     public final void closePanel(int featureId) {
-        if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null &&
-                mActionBar.isOverflowReserved() &&
+        if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
+                mDecorContentParent.canShowOverflowMenu() &&
                 !ViewConfiguration.get(getContext()).hasPermanentMenuKey()) {
-            mActionBar.hideOverflowMenu();
+            mDecorContentParent.hideOverflowMenu();
         } else if (featureId == FEATURE_CONTEXT_MENU) {
             closeContextMenu();
         } else {
@@ -784,7 +783,7 @@
     public final void closePanel(PanelFeatureState st, boolean doCallback) {
         // System.out.println("Close panel: isOpen=" + st.isOpen);
         if (doCallback && st.featureId == FEATURE_OPTIONS_PANEL &&
-                mActionBar != null && mActionBar.isOverflowMenuShowing()) {
+                mDecorContentParent != null && mDecorContentParent.isOverflowMenuShowing()) {
             checkCloseActionMenu(st.menu);
             return;
         }
@@ -830,7 +829,7 @@
         }
 
         mClosingActionMenu = true;
-        mActionBar.dismissPopupMenus();
+        mDecorContentParent.dismissPopups();
         Callback cb = getCallback();
         if (cb != null && !isDestroyed()) {
             cb.onPanelClosed(FEATURE_ACTION_BAR, menu);
@@ -876,7 +875,7 @@
         
         // Prepare the options panel if we have an action bar
         if ((featureId == FEATURE_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL)
-                && mActionBar != null) {
+                && mDecorContentParent != null) {
             st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false);
             if (st != null) {
                 st.isPrepared = false;
@@ -923,17 +922,15 @@
             
             boolean playSoundEffect = false;
             final PanelFeatureState st = getPanelState(featureId, true);
-            if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null &&
-                    mActionBar.isOverflowReserved() &&
+            if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
+                    mDecorContentParent.canShowOverflowMenu() &&
                     !ViewConfiguration.get(getContext()).hasPermanentMenuKey()) {
-                if (mActionBar.getVisibility() == View.VISIBLE) {
-                    if (!mActionBar.isOverflowMenuShowing()) {
-                        if (!isDestroyed() && preparePanel(st, event)) {
-                            playSoundEffect = mActionBar.showOverflowMenu();
-                        }
-                    } else {
-                        playSoundEffect = mActionBar.hideOverflowMenu();
+                if (!mDecorContentParent.isOverflowMenuShowing()) {
+                    if (!isDestroyed() && preparePanel(st, event)) {
+                        playSoundEffect = mDecorContentParent.showOverflowMenu();
                     }
+                } else {
+                    playSoundEffect = mDecorContentParent.hideOverflowMenu();
                 }
             } else {
                 if (st.isOpen || st.isHandled) {
@@ -1046,7 +1043,7 @@
             st.isHandled = true;
 
             // Only close down the menu if we don't have an action bar keeping it open.
-            if ((flags & Menu.FLAG_PERFORM_NO_CLOSE) == 0 && mActionBar == null) {
+            if ((flags & Menu.FLAG_PERFORM_NO_CLOSE) == 0 && mDecorContentParent == null) {
                 closePanel(st, true);
             }
         }
@@ -1068,7 +1065,7 @@
         boolean res = st.menu.performIdentifierAction(id, flags);
 
         // Only close down the menu if we don't have an action bar keeping it open.
-        if (mActionBar == null) {
+        if (mDecorContentParent == null) {
             closePanel(st, true);
         }
 
@@ -1103,12 +1100,12 @@
     }
 
     private void reopenMenu(boolean toggleMenuMode) {
-        if (mActionBar != null && mActionBar.isOverflowReserved() &&
+        if (mDecorContentParent != null && mDecorContentParent.canShowOverflowMenu() &&
                 (!ViewConfiguration.get(getContext()).hasPermanentMenuKey() ||
-                        mActionBar.isOverflowMenuShowPending())) {
+                        mDecorContentParent.isOverflowMenuShowPending())) {
             final Callback cb = getCallback();
-            if (!mActionBar.isOverflowMenuShowing() || !toggleMenuMode) {
-                if (cb != null && !isDestroyed() && mActionBar.getVisibility() == View.VISIBLE) {
+            if (!mDecorContentParent.isOverflowMenuShowing() || !toggleMenuMode) {
+                if (cb != null && !isDestroyed()) {
                     // If we have a menu invalidation pending, do it now.
                     if (mInvalidatePanelMenuPosted &&
                             (mInvalidatePanelMenuFeatures & (1 << FEATURE_OPTIONS_PANEL)) != 0) {
@@ -1123,11 +1120,11 @@
                     if (st.menu != null && !st.refreshMenuContent &&
                             cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
                         cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
-                        mActionBar.showOverflowMenu();
+                        mDecorContentParent.showOverflowMenu();
                     }
                 }
             } else {
-                mActionBar.hideOverflowMenu();
+                mDecorContentParent.hideOverflowMenu();
                 if (cb != null && !isDestroyed()) {
                     final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
                     cb.onPanelClosed(FEATURE_ACTION_BAR, st.menu);
@@ -1164,7 +1161,7 @@
 
         // If we have an action bar, initialize the menu with a context themed for it.
         if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR) &&
-                mActionBar != null) {
+                mDecorContentParent != null) {
             TypedValue outValue = new TypedValue();
             Resources.Theme currentTheme = context.getTheme();
             currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
@@ -1509,8 +1506,8 @@
         mIconRes = resId;
         mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON;
         mResourcesSetFlags &= ~FLAG_RESOURCE_SET_ICON_FALLBACK;
-        if (mActionBar != null) {
-            mActionBar.setIcon(resId);
+        if (mDecorContentParent != null) {
+            mDecorContentParent.setIcon(resId);
         }
     }
 
@@ -1520,13 +1517,14 @@
             return;
         }
         mIconRes = resId;
-        if (mActionBar != null && (!mActionBar.hasIcon() ||
+        if (mDecorContentParent != null && (!mDecorContentParent.hasIcon() ||
                 (mResourcesSetFlags & FLAG_RESOURCE_SET_ICON_FALLBACK) != 0)) {
             if (resId != 0) {
-                mActionBar.setIcon(resId);
+                mDecorContentParent.setIcon(resId);
                 mResourcesSetFlags &= ~FLAG_RESOURCE_SET_ICON_FALLBACK;
             } else {
-                mActionBar.setIcon(getContext().getPackageManager().getDefaultActivityIcon());
+                mDecorContentParent.setIcon(
+                        getContext().getPackageManager().getDefaultActivityIcon());
                 mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
             }
         }
@@ -1536,8 +1534,8 @@
     public void setLogo(int resId) {
         mLogoRes = resId;
         mResourcesSetFlags |= FLAG_RESOURCE_SET_LOGO;
-        if (mActionBar != null) {
-            mActionBar.setLogo(resId);
+        if (mDecorContentParent != null) {
+            mDecorContentParent.setLogo(resId);
         }
     }
 
@@ -1547,8 +1545,8 @@
             return;
         }
         mLogoRes = resId;
-        if (mActionBar != null && !mActionBar.hasLogo()) {
-            mActionBar.setLogo(resId);
+        if (mDecorContentParent != null && !mDecorContentParent.hasLogo()) {
+            mDecorContentParent.setLogo(resId);
         }
     }
 
@@ -1805,9 +1803,9 @@
             outState.putSparseParcelableArray(PANELS_TAG, panelStates);
         }
 
-        if (mActionBar != null) {
+        if (mDecorContentParent != null) {
             SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();
-            mActionBar.saveHierarchyState(actionBarStates);
+            mDecorContentParent.saveToolbarHierarchyState(actionBarStates);
             outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);
         }
 
@@ -1846,11 +1844,11 @@
             restorePanelState(panelStates);
         }
 
-        if (mActionBar != null) {
+        if (mDecorContentParent != null) {
             SparseArray<Parcelable> actionBarStates =
                     savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
             if (actionBarStates != null) {
-                mActionBar.restoreHierarchyState(actionBarStates);
+                mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);
             } else {
                 Log.w(TAG, "Missing saved instance states for action bar views! " +
                         "State will not be restored.");
@@ -2124,12 +2122,7 @@
         }
 
         public boolean superDispatchKeyEvent(KeyEvent event) {
-            if (super.dispatchKeyEvent(event)) {
-                return true;
-            }
-
-            // Not handled by the view hierarchy, does the action bar want it
-            // to cancel out of something special?
+            // Give priority to closing action modes if applicable.
             if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                 final int action = event.getAction();
                 // Back cancels action modes first.
@@ -2139,17 +2132,9 @@
                     }
                     return true;
                 }
-
-                // Next collapse any expanded action views.
-                if (mActionBar != null && mActionBar.hasExpandedActionView()) {
-                    if (action == KeyEvent.ACTION_UP) {
-                        mActionBar.collapseActionView();
-                    }
-                    return true;
-                }
             }
 
-            return false;
+            return super.dispatchKeyEvent(event);
         }
 
         public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
@@ -2844,8 +2829,8 @@
                 cb.onDetachedFromWindow();
             }
 
-            if (mActionBar != null) {
-                mActionBar.dismissPopupMenus();
+            if (mDecorContentParent != null) {
+                mDecorContentParent.dismissPopups();
             }
 
             if (mActionModePopup != null) {
@@ -3281,96 +3266,68 @@
             // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
             mDecor.makeOptionalFitsSystemWindows();
 
-            mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
-            if (mTitleView != null) {
-                mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
-                if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
-                    View titleContainer = findViewById(com.android.internal.R.id.title_container);
-                    if (titleContainer != null) {
-                        titleContainer.setVisibility(View.GONE);
-                    } else {
-                        mTitleView.setVisibility(View.GONE);
-                    }
-                    if (mContentParent instanceof FrameLayout) {
-                        ((FrameLayout)mContentParent).setForeground(null);
-                    }
-                } else {
-                    mTitleView.setText(mTitle);
+            final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
+                    com.android.internal.R.id.decor_content_parent);
+
+            if (decorContentParent != null) {
+                mDecorContentParent = decorContentParent;
+                mDecorContentParent.setWindowCallback(getCallback());
+                if (mDecorContentParent.getTitle() == null) {
+                    mDecorContentParent.setWindowTitle(mTitle);
                 }
-            } else {
-                mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
-                if (mActionBar != null) {
-                    mActionBar.setWindowCallback(getCallback());
-                    if (mActionBar.getTitle() == null) {
-                        mActionBar.setWindowTitle(mTitle);
-                    }
-                    final int localFeatures = getLocalFeatures();
-                    if ((localFeatures & (1 << FEATURE_PROGRESS)) != 0) {
-                        mActionBar.initProgress();
-                    }
-                    if ((localFeatures & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
-                        mActionBar.initIndeterminateProgress();
-                    }
 
-                    final ActionBarOverlayLayout abol = (ActionBarOverlayLayout) findViewById(
-                            com.android.internal.R.id.action_bar_overlay_layout);
-                    if (abol != null) {
-                        abol.setOverlayMode(
-                                (localFeatures & (1 << FEATURE_ACTION_BAR_OVERLAY)) != 0);
+                final int localFeatures = getLocalFeatures();
+                for (int i = 0; i < FEATURE_MAX; i++) {
+                    if ((localFeatures & (1 << i)) != 0) {
+                        mDecorContentParent.initFeature(i);
                     }
+                }
 
-                    boolean splitActionBar = false;
-                    final boolean splitWhenNarrow =
-                            (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0;
-                    if (splitWhenNarrow) {
-                        splitActionBar = getContext().getResources().getBoolean(
-                                com.android.internal.R.bool.split_action_bar_is_narrow);
-                    } else {
-                        splitActionBar = getWindowStyle().getBoolean(
-                                com.android.internal.R.styleable.Window_windowSplitActionBar, false);
-                    }
-                    final ActionBarContainer splitView = (ActionBarContainer) findViewById(
-                            com.android.internal.R.id.split_action_bar);
-                    if (splitView != null) {
-                        mActionBar.setSplitView(splitView);
-                        mActionBar.setSplitActionBar(splitActionBar);
-                        mActionBar.setSplitWhenNarrow(splitWhenNarrow);
+                mDecorContentParent.setUiOptions(mUiOptions);
 
-                        final ActionBarContextView cab = (ActionBarContextView) findViewById(
-                                com.android.internal.R.id.action_context_bar);
-                        cab.setSplitView(splitView);
-                        cab.setSplitActionBar(splitActionBar);
-                        cab.setSplitWhenNarrow(splitWhenNarrow);
-                    } else if (splitActionBar) {
-                        Log.e(TAG, "Requested split action bar with " +
-                                "incompatible window decor! Ignoring request.");
-                    }
+                if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
+                        (mIconRes != 0 && !mDecorContentParent.hasIcon())) {
+                    mDecorContentParent.setIcon(mIconRes);
+                } else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
+                        mIconRes == 0 && !mDecorContentParent.hasIcon()) {
+                    mDecorContentParent.setIcon(
+                            getContext().getPackageManager().getDefaultActivityIcon());
+                    mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
+                }
+                if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
+                        (mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
+                    mDecorContentParent.setLogo(mLogoRes);
+                }
 
-                    if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
-                            (mIconRes != 0 && !mActionBar.hasIcon())) {
-                        mActionBar.setIcon(mIconRes);
-                    } else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
-                            mIconRes == 0 && !mActionBar.hasIcon()) {
-                        mActionBar.setIcon(
-                                getContext().getPackageManager().getDefaultActivityIcon());
-                        mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
-                    }
-                    if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
-                            (mLogoRes != 0 && !mActionBar.hasLogo())) {
-                        mActionBar.setLogo(mLogoRes);
-                    }
-
-                    // Post the panel invalidate for later; avoid application onCreateOptionsMenu
-                    // being called in the middle of onCreate or similar.
-                    mDecor.post(new Runnable() {
-                        public void run() {
-                            // Invalidate if the panel menu hasn't been created before this.
-                            PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
-                            if (!isDestroyed() && (st == null || st.menu == null)) {
-                                invalidatePanelMenu(FEATURE_ACTION_BAR);
-                            }
+                // Post the panel invalidate for later; avoid application onCreateOptionsMenu
+                // being called in the middle of onCreate or similar.
+                mDecor.post(new Runnable() {
+                    public void run() {
+                        // Invalidate if the panel menu hasn't been created before this.
+                        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+                        if (!isDestroyed() && (st == null || st.menu == null)) {
+                            invalidatePanelMenu(FEATURE_ACTION_BAR);
                         }
-                    });
+                    }
+                });
+            } else {
+                mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
+                if (mTitleView != null) {
+                    mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
+                    if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
+                        View titleContainer = findViewById(
+                                com.android.internal.R.id.title_container);
+                        if (titleContainer != null) {
+                            titleContainer.setVisibility(View.GONE);
+                        } else {
+                            mTitleView.setVisibility(View.GONE);
+                        }
+                        if (mContentParent instanceof FrameLayout) {
+                            ((FrameLayout)mContentParent).setForeground(null);
+                        }
+                    } else {
+                        mTitleView.setText(mTitle);
+                    }
                 }
             }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 8eed414..466c8ed 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -261,13 +261,7 @@
     WindowState mLastInputMethodWindow = null;
     WindowState mLastInputMethodTargetWindow = null;
 
-    static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
-    static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
-    static final int RECENT_APPS_BEHAVIOR_DISMISS = 2;
-    static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 3;
-
-    RecentApplicationsDialog mRecentAppsDialog;
-    int mRecentAppsDialogHeldModifiers;
+    int mRecentAppsHeldModifiers;
     boolean mLanguageSwitchKeyPressed;
 
     int mLidState = LID_ABSENT;
@@ -807,52 +801,6 @@
         }
     };
 
-    /**
-     * Create (if necessary) and show or dismiss the recent apps dialog according
-     * according to the requested behavior.
-     */
-    void showOrHideRecentAppsDialog(final int behavior) {
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                if (mRecentAppsDialog == null) {
-                    mRecentAppsDialog = new RecentApplicationsDialog(mContext);
-                }
-                if (mRecentAppsDialog.isShowing()) {
-                    switch (behavior) {
-                        case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
-                        case RECENT_APPS_BEHAVIOR_DISMISS:
-                            mRecentAppsDialog.dismiss();
-                            break;
-                        case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
-                            mRecentAppsDialog.dismissAndSwitch();
-                            break;
-                        case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
-                        default:
-                            break;
-                    }
-                } else {
-                    switch (behavior) {
-                        case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
-                            mRecentAppsDialog.show();
-                            break;
-                        case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
-                            try {
-                                mWindowManager.setInTouchMode(false);
-                            } catch (RemoteException e) {
-                            }
-                            mRecentAppsDialog.show();
-                            break;
-                        case RECENT_APPS_BEHAVIOR_DISMISS:
-                        case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
-                        default:
-                            break;
-                    }
-                }
-            }
-        });
-    }
-
     /** {@inheritDoc} */
     @Override
     public void init(Context context, IWindowManager windowManager,
@@ -2261,21 +2209,20 @@
 
         // Display task switcher for ALT-TAB or Meta-TAB.
         if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
-            if (mRecentAppsDialogHeldModifiers == 0 && !keyguardOn) {
+            if (mRecentAppsHeldModifiers == 0 && !keyguardOn) {
                 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
                 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
                         || KeyEvent.metaStateHasModifiers(
                                 shiftlessModifiers, KeyEvent.META_META_ON)) {
-                    mRecentAppsDialogHeldModifiers = shiftlessModifiers;
-                    showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
+                    mRecentAppsHeldModifiers = shiftlessModifiers;
+                    showRecentApps(true);
                     return -1;
                 }
             }
-        } else if (!down && mRecentAppsDialogHeldModifiers != 0
-                && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
-            mRecentAppsDialogHeldModifiers = 0;
-            showOrHideRecentAppsDialog(keyguardOn ? RECENT_APPS_BEHAVIOR_DISMISS :
-                    RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
+        } else if (!down && mRecentAppsHeldModifiers != 0
+                && (metaState & mRecentAppsHeldModifiers) == 0) {
+            mRecentAppsHeldModifiers = 0;
+            hideRecentApps();
         }
 
         // Handle keyboard language switching.
@@ -2448,7 +2395,7 @@
                     statusbar.cancelPreloadRecentApps();
                 }
             } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException when showing recent apps", e);
+                Slog.e(TAG, "RemoteException when cancelling recent apps preload", e);
                 // re-acquire status bar service next time it is needed.
                 mStatusBarService = null;
             }
@@ -2457,19 +2404,46 @@
 
     private void toggleRecentApps() {
         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
-        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
         try {
             IStatusBarService statusbar = getStatusBarService();
             if (statusbar != null) {
                 statusbar.toggleRecentApps();
             }
         } catch (RemoteException e) {
+            Slog.e(TAG, "RemoteException when toggling recent apps", e);
+            // re-acquire status bar service next time it is needed.
+            mStatusBarService = null;
+        }
+    }
+
+    private void showRecentApps(boolean triggeredFromAltTab) {
+        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
+        try {
+            IStatusBarService statusbar = getStatusBarService();
+            if (statusbar != null) {
+                statusbar.showRecentApps(triggeredFromAltTab);
+            }
+        } catch (RemoteException e) {
             Slog.e(TAG, "RemoteException when showing recent apps", e);
             // re-acquire status bar service next time it is needed.
             mStatusBarService = null;
         }
     }
 
+    private void hideRecentApps() {
+        mPreloadedRecentApps = false; // preloading no longer needs to be canceled
+        try {
+            IStatusBarService statusbar = getStatusBarService();
+            if (statusbar != null) {
+                statusbar.hideRecentApps();
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "RemoteException when closing recent apps", e);
+            // re-acquire status bar service next time it is needed.
+            mStatusBarService = null;
+        }
+    }
+
     /**
      * A home key -> launch home action was detected.  Take the appropriate action
      * given the situation with the keyguard.
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index 2f0d7d6..bc55ed1 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -123,7 +123,7 @@
     }
 
     @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
+      public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_TAB) {
             // Ignore all meta keys other than SHIFT.  The app switch key could be a
             // fallback action chorded with ALT, META or even CTRL depending on the key map.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 2d0f6d1..01af753 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -193,6 +193,9 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = true; // STOPSHIP
 
+    // network sampling debugging
+    private static final boolean SAMPLE_DBG = false;
+
     private static final boolean LOGD_RULES = false;
 
     // TODO: create better separation between radio types and network types
@@ -219,10 +222,10 @@
     // Set network sampling interval at 12 minutes, this way, even if the timers get
     // aggregated, it will fire at around 15 minutes, which should allow us to
     // aggregate this timer with other timers (specially the socket keep alive timers)
-    private static final int DEFAULT_SAMPLING_INTERVAL_IN_SECONDS = (VDBG ? 30 : 12 * 60);
+    private static final int DEFAULT_SAMPLING_INTERVAL_IN_SECONDS = (SAMPLE_DBG ? 30 : 12 * 60);
 
     // start network sampling a minute after booting ...
-    private static final int DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS = (VDBG ? 30 : 60);
+    private static final int DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS = (SAMPLE_DBG ? 30 : 60);
 
     AlarmManager mAlarmManager;
 
@@ -504,10 +507,14 @@
 
     TelephonyManager mTelephonyManager;
 
+    // sequence number for Networks
     private final static int MIN_NET_ID = 10; // some reserved marks
     private final static int MAX_NET_ID = 65535;
     private int mNextNetId = MIN_NET_ID;
 
+    // sequence number of NetworkRequests
+    private int mNextNetworkRequestId = 1;
+
     public ConnectivityService(Context context, INetworkManagementService netd,
             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
         // Currently, omitting a NetworkFactory will create one internally
@@ -523,7 +530,7 @@
         NetworkCapabilities netCap = new NetworkCapabilities();
         netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
         netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
-        mDefaultRequest = new NetworkRequest(netCap, true);
+        mDefaultRequest = new NetworkRequest(netCap, true, nextNetworkRequestId());
         NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(),
                 NetworkRequestInfo.REQUEST);
         mNetworkRequests.put(mDefaultRequest, nri);
@@ -770,6 +777,10 @@
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
     }
 
+    private synchronized int nextNetworkRequestId() {
+        return mNextNetworkRequestId++;
+    }
+
     private synchronized int nextNetId() {
         int netId = mNextNetId;
         if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
@@ -5268,7 +5279,7 @@
             throw new IllegalArgumentException("Bad timeout specified");
         }
         NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
-                networkCapabilities));
+                networkCapabilities), false, nextNetworkRequestId());
         if (DBG) log("requestNetwork for " + networkRequest);
         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
                 NetworkRequestInfo.REQUEST);
@@ -5294,7 +5305,7 @@
         enforceAccessPermission();
 
         NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
-                networkCapabilities));
+                networkCapabilities), false, nextNetworkRequestId());
         if (DBG) log("listenForNetwork for " + networkRequest);
         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
                 NetworkRequestInfo.LISTEN);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 0b9570d..50553ee 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -2369,20 +2369,20 @@
 
     void setEnabledSessionInMainThread(SessionState session) {
         if (mEnabledSession != session) {
-            if (mEnabledSession != null) {
+            if (mEnabledSession != null && mEnabledSession.session != null) {
                 try {
                     if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
-                    mEnabledSession.method.setSessionEnabled(
-                            mEnabledSession.session, false);
+                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, false);
                 } catch (RemoteException e) {
                 }
             }
             mEnabledSession = session;
-            try {
-                if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
-                session.method.setSessionEnabled(
-                        session.session, true);
-            } catch (RemoteException e) {
+            if (mEnabledSession != null && mEnabledSession.session != null) {
+                try {
+                    if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
+                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, true);
+                } catch (RemoteException e) {
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index c1e5e5b..33e59a7 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -742,19 +742,10 @@
         int w = mThumbnailWidth;
         int h = mThumbnailHeight;
         if (w < 0) {
-            Configuration config = res.getConfiguration();
-            boolean useAlternateRecents = (config.smallestScreenWidthDp < 600);
-            if (useAlternateRecents) {
-                mThumbnailWidth = w =
-                   res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_width);
-                mThumbnailHeight = h =
-                   res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_height);
-            } else {
-                mThumbnailWidth = w =
-                    res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
-                mThumbnailHeight = h =
-                    res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
-            }
+            mThumbnailWidth = w =
+               res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_width);
+            mThumbnailHeight = h =
+               res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_height);
         }
 
         if (w > 0) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 5d744e6..ef9c711 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1816,7 +1816,7 @@
             }
             targetStack = sourceTask.stack;
             targetStack.moveToFront();
-            mWindowManager.moveTaskToTop(sourceTask.taskId);
+            mWindowManager.moveTaskToTop(targetStack.topTask().taskId);
             if (!addingToTask &&
                     (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
                 // In this case, we are adding the activity to an existing
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 5327ef4..986cb9b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -24,6 +24,7 @@
 import android.os.Message;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 
 import libcore.util.EmptyArray;
 
@@ -79,11 +80,12 @@
             new SparseArray<HdmiCecDeviceInfo>();
     // Set-like container for all local devices' logical address.
     // Key and value are same.
-    private final SparseArray<Integer> mLocalLogicalAddresses =
-            new SparseArray<Integer>();
+    private final SparseIntArray mLocalAddresses = new SparseIntArray();
 
     // Private constructor.  Use HdmiCecController.create().
     private HdmiCecController() {
+        // TODO: Consider restoring the local device addresses from persistent storage
+        //       to allocate the same addresses again if possible.
     }
 
     /**
@@ -109,6 +111,44 @@
     }
 
     /**
+     * Initialize {@link #mLocalAddresses} by allocating logical addresses for each hosted type.
+     *
+     * @param deviceTypes local device types
+     */
+    void initializeLocalDevices(int[] deviceTypes) {
+        for (int deviceType : deviceTypes) {
+            int preferred = getPreferredAddress(deviceType);
+            allocateLogicalAddress(deviceType, preferred, new AllocateLogicalAddressCallback() {
+                @Override
+                public void onAllocated(int deviceType, int logicalAddress) {
+                    addLogicalAddress(logicalAddress);
+                }
+            });
+        }
+    }
+
+    /**
+     * Get the preferred address for a given type.
+     *
+     * @param deviceType logical device type to get the address for
+     * @return preferred address; {@link HdmiCec#ADDR_UNREGISTERED} if not available.
+     */
+    private int getPreferredAddress(int deviceType) {
+        // Uses the data restored from persistent memory at boot up if they are available.
+        // Otherwise we return UNREGISTERED indicating there is no preferred address.
+        // Note that for address SPECIFIC_USE(14), HdmiCec.getTypeFromAddress() returns DEVICE_TV,
+        // meaning that we do not support device type video processor yet.
+        for (int i = 0; i < mLocalAddresses.size(); ++i) {
+            int address = mLocalAddresses.keyAt(i);
+            int type = HdmiCec.getTypeFromAddress(address);
+            if (type == deviceType) {
+                return address;
+            }
+        }
+        return HdmiCec.ADDR_UNREGISTERED;
+    }
+
+    /**
      * Interface to report allocated logical address.
      */
     interface AllocateLogicalAddressCallback {
@@ -322,7 +362,7 @@
      */
     int addLogicalAddress(int newLogicalAddress) {
         if (HdmiCec.isValidAddress(newLogicalAddress)) {
-            mLocalLogicalAddresses.append(newLogicalAddress, newLogicalAddress);
+            mLocalAddresses.put(newLogicalAddress, newLogicalAddress);
             return nativeAddLogicalAddress(mNativePtr, newLogicalAddress);
         } else {
             return -1;
@@ -337,7 +377,7 @@
     void clearLogicalAddress() {
         // TODO: consider to backup logical address so that new logical address
         // allocation can use it as preferred address.
-        mLocalLogicalAddresses.clear();
+        mLocalAddresses.clear();
         nativeClearLogicalAddress(mNativePtr);
     }
 
@@ -382,7 +422,7 @@
         // Can access command targeting devices available in local device or
         // broadcast command.
         return address == HdmiCec.ADDR_BROADCAST
-                || mLocalLogicalAddresses.get(address) != null;
+                || mLocalAddresses.indexOfKey(address) < 0;
     }
 
     private void onReceiveCommand(HdmiCecMessage message) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index ed48c12..7c136db 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -54,7 +54,10 @@
     @Override
     public void onStart() {
         mCecController = HdmiCecController.create(this);
-        if (mCecController == null) {
+        if (mCecController != null) {
+            mCecController.initializeLocalDevices(getContext().getResources()
+                    .getIntArray(com.android.internal.R.array.config_hdmiCecLogicalDeviceType));
+        } else {
             Slog.i(TAG, "Device does not support HDMI-CEC.");
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f9eabcd..61b3a89 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1663,7 +1663,10 @@
             updateAllSharedLibrariesLPw();
 
             for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
-                adjustCpuAbisForSharedUserLPw(setting.packages, true /* do dexopt */,
+                // NOTE: We ignore potential failures here during a system scan (like
+                // the rest of the commands above) because there's precious little we
+                // can do about it. A settings error is reported, though.
+                adjustCpuAbisForSharedUserLPw(setting.packages, null,
                         false /* force dexopt */, false /* defer dexopt */);
             }
 
@@ -5613,8 +5616,12 @@
             if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
                 // We don't do this here during boot because we can do it all
                 // at once after scanning all existing packages.
-                adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
-                        true, forceDex, (scanMode & SCAN_DEFER_DEX) != 0);
+                if (!adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
+                        pkg.applicationInfo.cpuAbi,
+                        forceDex, (scanMode & SCAN_DEFER_DEX) != 0)) {
+                    mLastScanError = PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
+                    return null;
+                }
             }
             // We don't expect installation to fail beyond this point,
             if ((scanMode&SCAN_MONITOR) != 0) {
@@ -5960,9 +5967,8 @@
         return pkg;
     }
 
-    public void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
-            boolean doDexOpt, boolean forceDexOpt, boolean deferDexOpt) {
-        String requiredInstructionSet = null;
+    private boolean adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
+            String requiredInstructionSet, boolean forceDexOpt, boolean deferDexOpt) {
         PackageSetting requirer = null;
         for (PackageSetting ps : packagesForUser) {
             if (ps.cpuAbiString != null) {
@@ -5970,20 +5976,16 @@
                 if (requiredInstructionSet != null) {
                     if (!instructionSet.equals(requiredInstructionSet)) {
                         // We have a mismatch between instruction sets (say arm vs arm64).
-                        //
-                        // TODO: We should rescan all the packages in a shared UID to check if
-                        // they do contain shared libs for other ABIs in addition to the ones we've
-                        // already extracted. For example, the package might contain both arm64-v8a
-                        // and armeabi-v7a shared libs, and we'd have chosen arm64-v8a on 64 bit
-                        // devices.
-                        String errorMessage = "Instruction set mismatch, " + requirer.pkg.packageName
-                                + " requires " + requiredInstructionSet + " whereas " + ps.pkg.packageName
+                        // bail out.
+                        String errorMessage = "Instruction set mismatch, "
+                                + ((requirer == null) ? "[caller]" : requirer.pkg)
+                                + " requires " + requiredInstructionSet + " whereas " + ps.pkg
                                 + " requires " + instructionSet;
                         Slog.e(TAG, errorMessage);
 
                         reportSettingsProblem(Log.WARN, errorMessage);
                         // Give up, don't bother making any other changes to the package settings.
-                        return;
+                        return false;
                     }
                 } else {
                     requiredInstructionSet = instructionSet;
@@ -5999,14 +6001,20 @@
                     if (ps.pkg != null) {
                         ps.pkg.applicationInfo.cpuAbi = requirer.cpuAbiString;
                         Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.cpuAbiString);
-                        if (doDexOpt) {
-                            performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true);
+
+                        if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) {
+                            ps.cpuAbiString = null;
+                            ps.pkg.applicationInfo.cpuAbi = null;
+                            return false;
+                        } else {
                             mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
                         }
                     }
                 }
             }
         }
+
+        return true;
     }
 
     private void setUpCustomResolverActivity(PackageParser.Package pkg) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 738ad32..2c38d3c 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -460,6 +460,24 @@
     }
 
     @Override
+    public void showRecentApps(boolean triggeredFromAltTab) {
+        if (mBar != null) {
+            try {
+                mBar.showRecentApps(triggeredFromAltTab);
+            } catch (RemoteException ex) {}
+        }
+    }
+
+    @Override
+    public void hideRecentApps() {
+        if (mBar != null) {
+            try {
+                mBar.hideRecentApps();
+            } catch (RemoteException ex) {}
+        }
+    }
+
+    @Override
     public void setCurrentUser(int newUserId) {
         if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);
         mCurrentUserId = newUserId;
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 99ec242..c20e38c 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -679,7 +679,7 @@
 
     Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
                             int appWidth, int appHeight, int orientation,
-                            Rect containingFrame, Rect contentInsets, Configuration configuration) {
+                            Rect containingFrame, Rect contentInsets) {
         Animation a;
         if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
             a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -700,15 +700,9 @@
                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
             mNextAppTransitionScaleUp =
                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
-            boolean useAlternateThumbnailAnimation = (configuration.smallestScreenWidthDp < 600);
-            if (useAlternateThumbnailAnimation) {
-                a = createAlternateThumbnailEnterExitAnimationLocked(
-                        getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
-                        transit, containingFrame, contentInsets);
-            } else {
-                a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
-                        appWidth, appHeight, transit);
-            }
+            a = createAlternateThumbnailEnterExitAnimationLocked(
+                    getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
+                    transit, containingFrame, contentInsets);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
                 String animName = mNextAppTransitionScaleUp ?
                         "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b61ba5c..c6fffbf 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3194,7 +3194,7 @@
             }
 
             Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
-                    mCurConfiguration.orientation, containingFrame, contentInsets, mCurConfiguration);
+                    mCurConfiguration.orientation, containingFrame, contentInsets);
             if (a != null) {
                 if (DEBUG_ANIM) {
                     RuntimeException e = null;
@@ -8677,7 +8677,7 @@
                 wtoken.deferClearAllDrawn = false;
             }
 
-            boolean useAlternateThumbnailAnimation = (mCurConfiguration.smallestScreenWidthDp < 600);
+            boolean useAlternateThumbnailAnimation = true;
             AppWindowAnimator appAnimator =
                     topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
             Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3c9d53e..1e79dcb 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -46,6 +46,7 @@
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
+import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 import android.view.WindowManager.LayoutParams;
@@ -151,6 +152,10 @@
     static final int READY_TO_SHOW = 3;
     /** Set when the window has been shown in the screen the first time. */
     static final int HAS_DRAWN = 4;
+
+    private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
+            View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+
     static String drawStateToString(int state) {
         switch (state) {
             case NO_SURFACE: return "NO_SURFACE";
@@ -1176,9 +1181,15 @@
             // content insets as well.
             int offsetTop = Math.max(w.mSystemDecorRect.top, w.mContentInsets.top);
             mTmpClipRect.set(w.mSystemDecorRect);
-            mTmpClipRect.offset(0, -offsetTop);
-            mTmpClipRect.intersect(mClipRect);
-            mTmpClipRect.offset(0, offsetTop);
+            // Don't apply the workaround to apps explicitly requesting fullscreen layout.
+            if ((w.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
+                    == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) {
+                mTmpClipRect.intersect(mClipRect);
+            } else {
+                mTmpClipRect.offset(0, -offsetTop);
+                mTmpClipRect.intersect(mClipRect);
+                mTmpClipRect.offset(0, offsetTop);
+            }
             clipRect = mTmpClipRect;
 
         }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 22e2a6e..9b3f7ac 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -124,8 +124,8 @@
             "com.android.server.usb.UsbService$Lifecycle";
     private static final String WIFI_SERVICE_CLASS =
             "com.android.server.wifi.WifiService";
-    private static final String WIFI_HOTSPOT_SERVICE_CLASS =
-            "com.android.server.wifi.hotspot.WifiHotspotService";
+    private static final String WIFI_PASSPOINT_SERVICE_CLASS =
+            "com.android.server.wifi.passpoint.WifiPasspointService";
     private static final String WIFI_P2P_SERVICE_CLASS =
             "com.android.server.wifi.p2p.WifiP2pService";
     private static final String HDMI_CEC_SERVICE_CLASS =
@@ -639,9 +639,9 @@
                 }
 
                 try {
-                    mSystemServiceManager.startService(WIFI_HOTSPOT_SERVICE_CLASS);
+                    mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
                 } catch (Throwable e) {
-                    reportWtf("starting Wi-Fi HotspotService", e);
+                    reportWtf("starting Wi-Fi PasspointService", e);
                 }
 
                 try {
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
new file mode 100644
index 0000000..6b7463c
--- /dev/null
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecomm;
+
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Represents a connection to a remote endpoint that carries voice traffic.
+ */
+public abstract class Connection {
+
+    private static String TAG = Connection.class.getSimpleName();
+
+    public interface Listener {
+        void onStateChanged(Connection c, int state);
+        void onAudioStateChanged(Connection c, CallAudioState state);
+        void onHandleChanged(Connection c, Uri newHandle);
+        void onSignalChanged(Connection c, Bundle details);
+        void onDisconnected(Connection c, int cause, String message);
+        void onDestroyed(Connection c);
+    }
+
+    public static class ListenerBase implements Listener {
+        /** {@inheritDoc} */
+        @Override
+        public void onStateChanged(Connection c, int state) {}
+
+        /** {@inheritDoc} */
+         @Override
+        public void onAudioStateChanged(Connection c, CallAudioState state) {}
+
+        /** {@inheritDoc} */
+        @Override
+        public void onHandleChanged(Connection c, Uri newHandle) {}
+
+        /** {@inheritDoc} */
+        @Override
+        public void onSignalChanged(Connection c, Bundle details) {}
+
+        /** {@inheritDoc} */
+        @Override
+        public void onDisconnected(Connection c, int cause, String message) {}
+
+        /** {@inheritDoc} */
+        @Override
+        public void onDestroyed(Connection c) {}
+    }
+
+    public final class State {
+        private State() {}
+
+        public static final int NEW = 0;
+        public static final int RINGING = 1;
+        public static final int DIALING = 2;
+        public static final int ACTIVE = 3;
+        public static final int HOLDING = 4;
+        public static final int DISCONNECTED = 5;
+    }
+
+    private final Set<Listener> mListeners = new HashSet<>();
+    private int mState = State.NEW;
+    private CallAudioState mCallAudioState;
+    private Uri mHandle;
+
+    /**
+     * Create a new Connection.
+     */
+    protected Connection() {}
+
+    /**
+     * @return The handle (e.g., phone number) to which this Connection
+     *         is currently communicating.
+     */
+    public final Uri getHandle() {
+        return mHandle;
+    }
+
+    /**
+     * @return The state of this Connection.
+     *
+     * @hide
+     */
+    public final int getState() {
+        return mState;
+    }
+
+    /**
+     * @return The audio state of the call, describing how its audio is currently
+     *         being routed by the system. This is {@code null} if this Connection
+     *         does not directly know about its audio state.
+     */
+    public final CallAudioState getCallAudioState() {
+        return mCallAudioState;
+    }
+
+    /**
+     * Assign a listener to be notified of state changes.
+     *
+     * @param l A listener.
+     * @return This Connection.
+     *
+     * @hide
+     */
+    public final Connection addConnectionListener(Listener l) {
+        mListeners.add(l);
+        return this;
+    }
+
+    /**
+     * Remove a previously assigned listener that was being notified of state changes.
+     *
+     * @param l A Listener.
+     * @return This Connection.
+     *
+     * @hide
+     */
+    public final Connection removeConnectionListener(Listener l) {
+        mListeners.remove(l);
+        return this;
+    }
+
+    /**
+     * Play a DTMF tone in this Connection.
+     *
+     * @param c A DTMF character.
+     *
+     * @hide
+     */
+    public final void playDtmfTone(char c) {
+        Log.d(TAG, "playDtmfTone " + c);
+        onPlayDtmfTone(c);
+    }
+
+    /**
+     * Stop any DTMF tones which may be playing in this Connection.
+     *
+     * @hide
+     */
+    public final void stopDtmfTone() {
+        Log.d(TAG, "stopDtmfTone");
+        onStopDtmfTone();
+    }
+
+    /**
+     * Disconnect this Connection. If and when the Connection can comply with
+     * this request, it will transition to the {@link State#DISCONNECTED}
+     * state and notify its listeners.
+     *
+     * @hide
+     */
+    public final void disconnect() {
+        Log.d(TAG, "disconnect");
+        onDisconnect();
+    }
+
+    /**
+     * Abort this Connection. The Connection will immediately transition to
+     * the {@link State#DISCONNECTED} state, and send no notifications of this
+     * or any other future events.
+     *
+     * @hide
+     */
+    public final void abort() {
+        Log.d(TAG, "abort");
+        onAbort();
+    }
+
+    /**
+     * Place this Connection on hold. If and when the Connection can comply with
+     * this request, it will transition to the {@link State#HOLDING}
+     * state and notify its listeners.
+     *
+     * @hide
+     */
+    public final void hold() {
+        Log.d(TAG, "hold");
+        onHold();
+    }
+
+    /**
+     * Un-hold this Connection. If and when the Connection can comply with
+     * this request, it will transition to the {@link State#ACTIVE}
+     * state and notify its listeners.
+     *
+     * @hide
+     */
+    public final void unhold() {
+        Log.d(TAG, "unhold");
+        onUnhold();
+    }
+
+    /**
+     * Accept a {@link State#RINGING} Connection. If and when the Connection
+     * can comply with this request, it will transition to the {@link State#ACTIVE}
+     * state and notify its listeners.
+     *
+     * @hide
+     */
+    public final void answer() {
+        Log.d(TAG, "answer");
+        if (mState == State.RINGING) {
+            onAnswer();
+        }
+    }
+
+    /**
+     * Reject a {@link State#RINGING} Connection. If and when the Connection
+     * can comply with this request, it will transition to the {@link State#ACTIVE}
+     * state and notify its listeners.
+     *
+     * @hide
+     */
+    public final void reject() {
+        Log.d(TAG, "reject");
+        if (mState == State.RINGING) {
+            onReject();
+        }
+    }
+
+    /**
+     * Inform this Connection that the state of its audio output has been changed externally.
+     *
+     * @param state The new audio state.
+     */
+    public void setAudioState(CallAudioState state) {
+        Log.d(TAG, "setAudioState " + state);
+        onSetAudioState(state);
+    }
+
+    /**
+     * @param state An integer value from {@link State}.
+     * @return A string representation of the value.
+     */
+    public static String stateToString(int state) {
+        switch (state) {
+            case State.NEW:
+                return "NEW";
+            case State.RINGING:
+                return "RINGING";
+            case State.DIALING:
+                return "DIALING";
+            case State.ACTIVE:
+                return "ACTIVE";
+            case State.HOLDING:
+                return "HOLDING";
+            case State.DISCONNECTED:
+                return "DISCONNECTED";
+            default:
+                Log.wtf(TAG, "Unknown state " + state);
+                return "UNKNOWN";
+        }
+    }
+
+    /**
+     * Sets the value of the {@link #getHandle()} property and notifies listeners.
+     *
+     * @param handle The new handle.
+     */
+    protected void setHandle(Uri handle) {
+        Log.d(TAG, "setHandle " + handle);
+        // TODO: Enforce super called
+        mHandle = handle;
+        for (Listener l : mListeners) {
+            l.onHandleChanged(this, handle);
+        }
+    }
+
+    /**
+     * Sets state to active (e.g., an ongoing call where two or more parties can actively
+     * communicate).
+     */
+    protected void setActive() {
+        setState(State.ACTIVE);
+    }
+
+    /**
+     * Sets state to ringing (e.g., an inbound ringing call).
+     */
+    protected void setRinging() {
+        setState(State.RINGING);
+    }
+
+    /**
+     * Sets state to dialing (e.g., dialing an outbound call).
+     */
+    protected void setDialing() {
+        setState(State.DIALING);
+    }
+
+    /**
+     * Sets state to be on hold.
+     */
+    protected void setOnHold() {
+        setState(State.HOLDING);
+    }
+
+    /**
+     * Sets state to disconnected. This will first notify listeners with an
+     * {@link Listener#onStateChanged(Connection, int)} event, then will fire an
+     * {@link Listener#onDisconnected(Connection, int, String)} event with additional
+     * details.
+     *
+     * @param cause The reason for the disconnection, any of
+     *         {@link android.telephony.DisconnectCause}.
+     * @param message Optional call-service-provided message about the disconnect.
+     */
+    protected void setDisconnected(int cause, String message) {
+        setState(State.DISCONNECTED);
+        Log.d(TAG, "Disconnected with cause " + cause + " message " + message);
+        for (Listener l : mListeners) {
+            l.onDisconnected(this, cause, message);
+        }
+    }
+
+    /**
+     * Notifies this Connection and listeners that the {@link #getCallAudioState()} property
+     * has a new value.
+     *
+     * @param state The new call audio state.
+     */
+    protected void onSetAudioState(CallAudioState state) {
+        // TODO: Enforce super called
+        this.mCallAudioState = state;
+        for (Listener l : mListeners) {
+            l.onAudioStateChanged(this, state);
+        }
+    }
+
+    /**
+     * Notifies this Connection and listeners of a change in the current signal levels
+     * for the underlying data transport.
+     *
+     * @param details A {@link android.os.Bundle} containing details of the current level.
+     */
+    protected void onSetSignal(Bundle details) {
+        // TODO: Enforce super called
+        for (Listener l : mListeners) {
+            l.onSignalChanged(this, details);
+        }
+    }
+
+    /**
+     * Notifies this Connection of a request to play a DTMF tone.
+     *
+     * @param c A DTMF character.
+     */
+    protected void onPlayDtmfTone(char c) {}
+
+    /**
+     * Notifies this Connection of a request to stop any currently playing DTMF tones.
+     */
+    protected void onStopDtmfTone() {}
+
+    /**
+     * Notifies this Connection of a request to disconnect.
+     */
+    protected void onDisconnect() {}
+
+    /**
+     * Notifies this Connection of a request to abort.
+     */
+    protected void onAbort() {}
+
+    /**
+     * Notifies this Connection of a request to hold.
+     */
+    protected void onHold() {}
+
+    /**
+     * Notifies this Connection of a request to exit a hold state.
+     */
+    protected void onUnhold() {}
+
+    /**
+     * Notifies this Connection, which is in {@link State#RINGING}, of
+     * a request to accept.
+     */
+    protected void onAnswer() {}
+
+    /**
+     * Notifies this Connection, which is in {@link State#RINGING}, of
+     * a request to reject.
+     */
+    protected void onReject() {}
+
+    private void setState(int state) {
+        Log.d(TAG, "setState: " + stateToString(state));
+        this.mState = state;
+        for (Listener l : mListeners) {
+            l.onStateChanged(this, state);
+        }
+    }
+}
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
new file mode 100644
index 0000000..c1f1871
--- /dev/null
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecomm;
+
+import android.os.Bundle;
+import android.net.Uri;
+
+/**
+ * Simple data container encapsulating a request to some entity to
+ * create a new {@link Connection}.
+ */
+public final class ConnectionRequest {
+
+    // TODO: Token to limit recursive invocations
+    // TODO: Consider upgrading "mHandle" to ordered list of handles, indicating a set of phone
+    //         numbers that would satisfy the client's needs, in order of preference
+    private final Uri mHandle;
+    private final Bundle mExtras;
+
+    public ConnectionRequest(Uri handle, Bundle extras) {
+        mHandle = handle; mExtras = extras;
+    }
+
+    /**
+     * The handle (e.g., phone number) to which the {@link Connection} is to connect.
+     */
+    public Uri getHandle() { return mHandle; }
+
+    /**
+     * Application-specific extra data. Used for passing back information from an incoming
+     * call {@code Intent}, and for any proprietary extensions arranged between a client
+     * and servant {@code ConnectionService} which agree on a vocabulary for such data.
+     */
+    public Bundle getExtras() { return mExtras; }
+
+    public String toString() {
+        return String.format("PhoneConnectionRequest %s %s",
+                mHandle == null
+                        ? Uri.EMPTY
+                        : ConnectionService.toLogSafePhoneNumber(mHandle.toString()),
+                mExtras == null ? "" : mExtras);
+    }
+}
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
new file mode 100644
index 0000000..aba4579
--- /dev/null
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecomm;
+
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link android.app.Service} that provides telephone connections to
+ * processes running on an Android device.
+ */
+public abstract class ConnectionService extends CallService {
+    private static final String TAG = ConnectionService.class.getSimpleName();
+
+    // STOPSHIP: Debug Logging should be conditional on a debug flag or use a set of
+    // logging functions that make it automaticaly so.
+
+    // Flag controlling whether PII is emitted into the logs
+    private static final boolean PII_DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private static final Connection NULL_CONNECTION = new Connection() {};
+
+    // Mappings from Connections to IDs as understood by the current CallService implementation
+    private final Map<String, Connection> mConnectionById = new HashMap<>();
+    private final Map<Connection, String> mIdByConnection = new HashMap<>();
+
+    private final Connection.Listener mConnectionListener = new Connection.Listener() {
+        @Override
+        public void onStateChanged(Connection c, int state) {
+            String id = mIdByConnection.get(c);
+            Log.d(TAG, "Adapter set state " + id + " " + Connection.stateToString(state));
+            switch (state) {
+                case Connection.State.ACTIVE:
+                    getAdapter().setActive(id);
+                    break;
+                case Connection.State.DIALING:
+                    getAdapter().setDialing(id);
+                    break;
+                case Connection.State.DISCONNECTED:
+                    // Handled in onDisconnected()
+                    break;
+                case Connection.State.HOLDING:
+                    getAdapter().setOnHold(id);
+                    break;
+                case Connection.State.NEW:
+                    // Nothing to tell Telecomm
+                    break;
+                case Connection.State.RINGING:
+                    getAdapter().setRinging(id);
+                    break;
+            }
+        }
+
+        @Override
+        public void onDisconnected(Connection c, int cause, String message) {
+            String id = mIdByConnection.get(c);
+            Log.d(TAG, "Adapter set disconnected " + cause + " " + message);
+            getAdapter().setDisconnected(id, cause, message);
+        }
+
+        @Override
+        public void onHandleChanged(Connection c, Uri newHandle) {
+            // TODO: Unsupported yet
+        }
+
+        @Override
+        public void onAudioStateChanged(Connection c, CallAudioState state) {
+            // TODO: Unsupported yet
+        }
+
+        @Override
+        public void onSignalChanged(Connection c, Bundle details) {
+            // TODO: Unsupported yet
+        }
+
+        @Override
+        public void onDestroyed(Connection c) {
+            removeConnection(c);
+        }
+    };
+
+    @Override
+    public final void isCompatibleWith(final CallInfo callInfo) {
+        Log.d(TAG, "isCompatibleWith " + callInfo);
+        onFindSubscriptions(
+                callInfo.getHandle(),
+                new Response<Uri, Subscription>() {
+                    @Override
+                    public void onResult(Uri handle, Subscription... result) {
+                        boolean isCompatible = result.length > 0;
+                        Log.d(TAG, "adapter setIsCompatibleWith "
+                                + callInfo.getId() + " " + isCompatible);
+                        getAdapter().setIsCompatibleWith(callInfo.getId(), isCompatible);
+                    }
+
+                    @Override
+                    public void onError(Uri handle, String reason) {
+                        Log.wtf(TAG, "Error in onFindSubscriptions " + callInfo.getHandle()
+                                + " error: " + reason);
+                        getAdapter().setIsCompatibleWith(callInfo.getId(), false);
+                    }
+                }
+        );
+    }
+
+    @Override
+    public final void call(final CallInfo callInfo) {
+        Log.d(TAG, "call " + callInfo);
+        onCreateConnections(
+                new ConnectionRequest(
+                        callInfo.getHandle(),
+                        callInfo.getExtras()),
+                new Response<ConnectionRequest, Connection>() {
+                    @Override
+                    public void onResult(ConnectionRequest request, Connection... result) {
+                        if (result.length != 1) {
+                            Log.d(TAG, "adapter handleFailedOutgoingCall " + callInfo);
+                            getAdapter().handleFailedOutgoingCall(
+                                    callInfo.getId(),
+                                    "Created " + result.length + " Connections, expected 1");
+                            for (Connection c : result) {
+                                c.abort();
+                            }
+                        } else {
+                            addConnection(callInfo.getId(), result[0]);
+                            Log.d(TAG, "adapter handleSuccessfulOutgoingCall "
+                                    + callInfo.getId());
+                            getAdapter().handleSuccessfulOutgoingCall(callInfo.getId());
+                        }
+                    }
+
+                    @Override
+                    public void onError(ConnectionRequest request, String reason) {
+                        getAdapter().handleFailedOutgoingCall(callInfo.getId(), reason);
+                    }
+                }
+        );
+    }
+
+    @Override
+    public final void abort(String callId) {
+        Log.d(TAG, "abort " + callId);
+        findConnectionForAction(callId, "abort").abort();
+    }
+
+    @Override
+    public final void setIncomingCallId(final String callId, Bundle extras) {
+        Log.d(TAG, "setIncomingCallId " + callId + " " + extras);
+        onCreateIncomingConnection(
+                new ConnectionRequest(
+                        null,  // TODO: Can we obtain this from "extras"?
+                        extras),
+                new Response<ConnectionRequest, Connection>() {
+                    @Override
+                    public void onResult(ConnectionRequest request, Connection... result) {
+                        if (result.length != 1) {
+                            Log.d(TAG, "adapter handleFailedOutgoingCall " + callId);
+                            getAdapter().handleFailedOutgoingCall(
+                                    callId,
+                                    "Created " + result.length + " Connections, expected 1");
+                            for (Connection c : result) {
+                                c.abort();
+                            }
+                        } else {
+                            addConnection(callId, result[0]);
+                            Log.d(TAG, "adapter notifyIncomingCall " + callId);
+                            // TODO: Uri.EMPTY is because CallInfo crashes when Parceled with a
+                            // null URI ... need to fix that at its cause!
+                            getAdapter().notifyIncomingCall(new CallInfo(
+                                    callId,
+                                    connectionStateToCallState(result[0].getState()),
+                                    request.getHandle() /* result[0].getHandle() == null
+                                            ? Uri.EMPTY : result[0].getHandle() */));
+                        }
+                    }
+
+                    @Override
+                    public void onError(ConnectionRequest request, String reason) {
+                        Log.d(TAG, "adapter failed setIncomingCallId " + request + " " + reason);
+                    }
+                }
+        );
+    }
+
+    @Override
+    public final void answer(String callId) {
+        Log.d(TAG, "answer " + callId);
+        findConnectionForAction(callId, "answer").answer();
+    }
+
+    @Override
+    public final void reject(String callId) {
+        Log.d(TAG, "reject " + callId);
+        findConnectionForAction(callId, "reject").reject();
+    }
+
+    @Override
+    public final void disconnect(String callId) {
+        Log.d(TAG, "disconnect " + callId);
+        findConnectionForAction(callId, "disconnect").disconnect();
+    }
+
+    @Override
+    public final void hold(String callId) {
+        Log.d(TAG, "hold " + callId);
+        findConnectionForAction(callId, "hold").hold();
+    }
+
+    @Override
+    public final void unhold(String callId) {
+        Log.d(TAG, "unhold " + callId);
+        findConnectionForAction(callId, "unhold").unhold();
+    }
+
+    @Override
+    public final void playDtmfTone(String callId, char digit) {
+        Log.d(TAG, "playDtmfTone " + callId + " " + Character.toString(digit));
+        findConnectionForAction(callId, "playDtmfTone").playDtmfTone(digit);
+    }
+
+    @Override
+    public final void stopDtmfTone(String callId) {
+        Log.d(TAG, "stopDtmfTone " + callId);
+        findConnectionForAction(callId, "stopDtmfTone").stopDtmfTone();
+    }
+
+    @Override
+    public final void onAudioStateChanged(String callId, CallAudioState audioState) {
+        Log.d(TAG, "onAudioStateChanged " + callId + " " + audioState);
+        findConnectionForAction(callId, "onAudioStateChanged").setAudioState(audioState);
+    }
+
+    /**
+     * Find a set of Subscriptions matching a given handle (e.g. phone number).
+     *
+     * @param handle A handle (e.g. phone number) with which to connect.
+     * @param callback A callback for providing the result.
+     */
+    public void onFindSubscriptions(
+            Uri handle,
+            Response<Uri, Subscription> callback) {}
+
+    /**
+     * Create a Connection given a request.
+     *
+     * @param request Data encapsulating details of the desired Connection.
+     * @param callback A callback for providing the result.
+     */
+    public void onCreateConnections(
+            ConnectionRequest request,
+            Response<ConnectionRequest, Connection> callback) {}
+
+    /**
+     * Create a Connection to match an incoming connection notification.
+     *
+     * @param request Data encapsulating details of the desired Connection.
+     * @param callback A callback for providing the result.
+     */
+    public void onCreateIncomingConnection(
+            ConnectionRequest request,
+            Response<ConnectionRequest, Connection> callback) {}
+
+    static String toLogSafePhoneNumber(String number) {
+        // For unknown number, log empty string.
+        if (number == null) {
+            return "";
+        }
+
+        if (PII_DEBUG) {
+            // When PII_DEBUG is true we emit PII.
+            return number;
+        }
+
+        // Do exactly same thing as Uri#toSafeString() does, which will enable us to compare
+        // sanitized phone numbers.
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < number.length(); i++) {
+            char c = number.charAt(i);
+            if (c == '-' || c == '@' || c == '.') {
+                builder.append(c);
+            } else {
+                builder.append('x');
+            }
+        }
+        return builder.toString();
+    }
+
+    private CallState connectionStateToCallState(int connectionState) {
+        switch (connectionState) {
+            case Connection.State.NEW:
+                return CallState.NEW;
+            case Connection.State.RINGING:
+                return CallState.RINGING;
+            case Connection.State.DIALING:
+                return CallState.DIALING;
+            case Connection.State.ACTIVE:
+                return CallState.ACTIVE;
+            case Connection.State.HOLDING:
+                return CallState.ON_HOLD;
+            case Connection.State.DISCONNECTED:
+                return CallState.DISCONNECTED;
+            default:
+                Log.wtf(TAG, "Unknown Connection.State " + connectionState);
+                return CallState.NEW;
+        }
+    }
+
+    private void addConnection(String callId, Connection connection) {
+        mConnectionById.put(callId, connection);
+        mIdByConnection.put(connection, callId);
+        connection.addConnectionListener(mConnectionListener);
+    }
+
+    private void removeConnection(Connection connection) {
+        connection.removeConnectionListener(mConnectionListener);
+        mConnectionById.remove(mIdByConnection.get(connection));
+        mIdByConnection.remove(connection);
+    }
+
+    private Connection findConnectionForAction(String callId, String action) {
+        if (mConnectionById.containsKey(callId)) {
+            return mConnectionById.get(callId);
+        }
+        Log.wtf(TAG, action + " - Cannot find Connection \"" + callId + "\"");
+        return NULL_CONNECTION;
+    }
+}
\ No newline at end of file
diff --git a/telecomm/java/android/telecomm/Response.java b/telecomm/java/android/telecomm/Response.java
new file mode 100644
index 0000000..14f8340
--- /dev/null
+++ b/telecomm/java/android/telecomm/Response.java
@@ -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.
+ */
+
+package android.telecomm;
+
+/**
+ * Used to inform a client of asynchronously returned results.
+ */
+public interface Response<IN, OUT> {
+
+    /**
+     * Provide a set of results.
+     *
+     * @param request The original request.
+     * @param result The results.
+     */
+    void onResult(IN request, OUT... result);
+
+    /**
+     * Indicates the inability to provide results.
+     *
+     * @param request The original request.
+     * @param reason The reason for the failure.
+     */
+    void onError(IN request, String reason);
+}
diff --git a/telecomm/java/android/telecomm/Subscription.java b/telecomm/java/android/telecomm/Subscription.java
new file mode 100644
index 0000000..f187f4d
--- /dev/null
+++ b/telecomm/java/android/telecomm/Subscription.java
@@ -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.
+ */
+
+package android.telecomm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a distinct subscription, line of service or call placement method that
+ * a {@link ConnectionService} can use to place phone calls.
+ */
+public class Subscription implements Parcelable {
+
+    public Subscription() {}
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {}
+
+    public static final Parcelable.Creator<Subscription> CREATOR
+            = new Parcelable.Creator<Subscription>() {
+        public Subscription createFromParcel(Parcel in) {
+            return new Subscription(in);
+        }
+
+        public Subscription[] newArray(int size) {
+            return new Subscription[size];
+        }
+    };
+
+    private Subscription(Parcel in) {}
+}
diff --git a/telephony/java/android/telephony/CallStateListener.java b/telephony/java/android/telephony/CallStateListener.java
deleted file mode 100644
index e2ffbfa..0000000
--- a/telephony/java/android/telephony/CallStateListener.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony;
-
-import android.annotation.PrivateApi;
-
-/** @hide */
-@PrivateApi
-public interface CallStateListener {
-    /**
-     * Notify of a new or updated call.
-     * Any time the state of a call is updated, it will alert any listeners. This includes changes
-     * of state such as when a call is put on hold or conferenced.
-     *
-     * @param callId a unique ideCntifier for a given call that can be used to track state changes
-     * @param state the new state of the call.
-     *              {@see com.android.services.telephony.common.Call$State}
-     * @param number the phone number of the call. For some states, this may be blank. However, it
-     *               will be populated for any initial state.
-     */
-    public void onCallStateChanged(int callId, int state, String number);
-}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2bf9ef1..5d485c5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -32,7 +32,6 @@
 
 import com.android.internal.telephony.IPhoneSubInfo;
 import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.ITelephonyListener;
 import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.RILConstants;
@@ -82,40 +81,8 @@
         static final int NEVER_USE = 2;
     }
 
-    private final HashMap<CallStateListener,Listener> mListeners
-            = new HashMap<CallStateListener,Listener>();
     private final Context mContext;
 
-    private static class Listener extends ITelephonyListener.Stub {
-        final CallStateListener mListener;
-        private static final int WHAT = 1;
-
-        private Handler mHandler = new Handler() {
-            @Override
-            public void handleMessage(Message msg) {
-                mListener.onCallStateChanged(msg.arg1, msg.arg2, (String)msg.obj);
-            }
-        };
-
-        Listener(CallStateListener listener) {
-            mListener = listener;
-        }
-
-        @Override
-        public void onUpdate(final int callId, final int state, final String number) {
-            if (mHandler != null) {
-                mHandler.sendMessage(mHandler.obtainMessage(WHAT, callId, state, number));
-            }
-        }
-
-        void clearQueue() {
-            mHandler.removeMessages(WHAT);
-
-            // Don't accept more incoming binder calls either.
-            mHandler = null;
-        }
-    }
-
     /** @hide */
     public TelephonyManager(Context context) {
         Context appContext = context.getApplicationContext();
@@ -2047,46 +2014,6 @@
 
     /** @hide */
     @PrivateApi
-    public void toggleHold() {
-        try {
-            getITelephony().toggleHold();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#toggleHold", e);
-        }
-    }
-
-    /** @hide */
-    @PrivateApi
-    public void merge() {
-        try {
-            getITelephony().merge();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#merge", e);
-        }
-    }
-
-    /** @hide */
-    @PrivateApi
-    public void swap() {
-        try {
-            getITelephony().swap();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#swap", e);
-        }
-    }
-
-    /** @hide */
-    @PrivateApi
-    public void mute(boolean mute) {
-        try {
-            getITelephony().mute(mute);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#mute", e);
-        }
-    }
-
-    /** @hide */
-    @PrivateApi
     public void silenceRinger() {
         try {
             getITelephony().silenceRinger();
@@ -2322,56 +2249,4 @@
         }
         return false;
     }
-
-    /** @hide */
-    @PrivateApi
-    public void playDtmfTone(char digit, boolean timedShortCode) {
-        try {
-            getITelephony().playDtmfTone(digit, timedShortCode);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#playDtmfTone", e);
-        }
-    }
-
-    /** @hide */
-    @PrivateApi
-    public void stopDtmfTone() {
-        try {
-            getITelephony().stopDtmfTone();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#stopDtmfTone", e);
-        }
-    }
-
-    /** @hide */
-    @PrivateApi
-    public void addCallStateListener(CallStateListener listener) {
-        try {
-            if (listener == null) {
-                throw new RuntimeException("Listener can't be null");
-            }
-            if (!mListeners.containsKey(listener)) {
-                final Listener l = new Listener(listener);
-                mListeners.put(listener, l);
-                getITelephony().addListener(l);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#addListener", e);
-        }
-    }
-
-    /** @hide */
-    @PrivateApi
-    public void removeCallStateListener(CallStateListener listener) {
-        try {
-            final Listener l = mListeners.remove(listener);
-            if (l != null) {
-                // Make sure that no callbacks that are already in flight come.
-                l.clearQueue();
-                getITelephony().removeListener(l);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#removeListener", e);
-        }
-    }
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 8b80bfa..baacb74 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -21,8 +21,6 @@
 import android.telephony.CellInfo;
 import android.telephony.NeighboringCellInfo;
 
-import com.android.internal.telephony.ITelephonyListener;
-
 import java.util.List;
 
 import java.util.List;
@@ -438,47 +436,4 @@
      * @return true on success; false on any failure.
      */
     boolean setPreferredNetworkType(int networkType);
-
-    /**
-     * Put a call on hold.
-     */
-     void toggleHold();
-
-     /**
-      * Merge foreground and background calls.
-      */
-     void merge();
-
-     /**
-      * Swap foreground and background calls.
-      */
-     void swap();
-
-     /**
-      * Mute the phone.
-      */
-     void mute(boolean mute);
-
-    /**
-     * Start playing DTMF tone for the specified digit.
-     *
-     * @param digit the digit that corresponds with the desired tone.
-     * @param timedShortcode whether the specified digit should be played as a timed short code.
-     */
-     void playDtmfTone(char digit, boolean timedShortCode);
-
-     /**
-      * Stop playing DTMF tones.
-      */
-     void stopDtmfTone();
-
-     /**
-       * Register a callback.
-       */
-      void addListener(ITelephonyListener listener);
-
-      /**
-       * Unregister a callback.
-       */
-      void removeListener(ITelephonyListener listener);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyListener.aidl b/telephony/java/com/android/internal/telephony/ITelephonyListener.aidl
deleted file mode 100644
index c226217..0000000
--- a/telephony/java/com/android/internal/telephony/ITelephonyListener.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-/**
- * Interface used to register a listener that gets more detailed call state information than
- * {@link android.telephony.PhoneStateListener}
- *
- * {@hide}
- */
-oneway interface ITelephonyListener {
-    void onUpdate(int callId, int state, String number);
-}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
index 4938579..5b0aa66 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -108,7 +108,6 @@
 
             mToggle = !mToggle;
 
-            /*
             mRunningAnimations.add(new RenderNodeAnimator(
                     mX, mToggle ? 400.0f : 200.0f));
 
@@ -131,7 +130,8 @@
                 RenderNodeAnimator anim = mRunningAnimations.get(i);
                 anim.setInterpolator(interp);
                 anim.setDuration(1000);
-                anim.start(this);
+                anim.setTarget(this);
+                anim.start();
             }
 
             if (mToggle) {
@@ -147,7 +147,6 @@
                     }
                 });
             }
-            */
             return true;
         }
     }
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index b5b12d8..c7715ad 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -77,7 +77,8 @@
                     RenderNodeAnimator.TRANSLATION_Y, dy * delta);
             animator.setDuration(DURATION);
             if (child == clickedView) logTranslationY(clickedView);
-            animator.start(child);
+            animator.setTarget(child);
+            animator.start();
             if (child == clickedView) logTranslationY(clickedView);
         }
         //mHandler.postDelayed(mLaunchActivity, (long) (DURATION * .4));
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0535fe0..9ccd810 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -111,8 +111,6 @@
 
     Messenger getWifiServiceMessenger();
 
-    Messenger getWifiStateMachineMessenger();
-
     String getConfigFile();
 
     void enableTdls(String remoteIPAddress, boolean enable);
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 1cb9546..3e3b6e3 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -16,6 +16,8 @@
 
 package android.net.wifi;
 
+import android.net.wifi.passpoint.PasspointInfo;
+import android.net.wifi.passpoint.PasspointManager;
 import android.os.Parcelable;
 import android.os.Parcel;
 
@@ -77,6 +79,13 @@
     public int distanceSdCm;
 
     /**
+     * Passpoint ANQP information. This is not fetched automatically.
+     * Use {@link PasspointManager#requestAnqpInfo} to request ANQP info.
+     * {@hide}
+     */
+    public PasspointInfo passpoint;
+
+    /**
      * {@hide}
      */
     public final static int UNSPECIFIED = -1;
@@ -122,6 +131,8 @@
             distanceCm = source.distanceCm;
             distanceSdCm = source.distanceSdCm;
             seen = source.seen;
+            if (source.passpoint != null)
+                passpoint = new PasspointInfo(source.passpoint);
         }
     }
 
@@ -155,6 +166,9 @@
         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
                 append("(cm)");
 
+        if (passpoint != null)
+            sb.append(", passpoint: [").append(passpoint.toString()).append("]");
+
         return sb.toString();
     }
 
@@ -178,6 +192,12 @@
         dest.writeLong(timestamp);
         dest.writeInt(distanceCm);
         dest.writeInt(distanceSdCm);
+        if (passpoint != null) {
+            dest.writeInt(1);
+            passpoint.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -188,7 +208,7 @@
                 if (in.readInt() == 1) {
                     wifiSsid = WifiSsid.CREATOR.createFromParcel(in);
                 }
-                return new ScanResult(
+                ScanResult sr = new ScanResult(
                     wifiSsid,
                     in.readString(),
                     in.readString(),
@@ -198,6 +218,10 @@
                     in.readInt(),
                     in.readInt()
                 );
+                if (in.readInt() == 1) {
+                    sr.passpoint = PasspointInfo.CREATOR.createFromParcel(in);
+                }
+                return sr;
             }
 
             public ScanResult[] newArray(int size) {
diff --git a/wifi/java/android/net/wifi/WifiLinkLayerStats.java b/wifi/java/android/net/wifi/WifiLinkLayerStats.java
new file mode 100644
index 0000000..922eddd
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiLinkLayerStats.java
@@ -0,0 +1,189 @@
+/*
+ * 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.net.wifi;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.text.TextUtils;
+import java.util.HashMap;
+import java.util.Date;
+import java.util.ArrayList;
+
+import java.util.BitSet;
+
+/**
+ * A class representing link layer statistics collected over a Wifi Interface.
+ */
+/** {@hide} */
+public class WifiLinkLayerStats implements Parcelable {
+    private static final String TAG = "WifiLinkLayerStats";
+
+    /**
+     * The current status of this network configuration entry.
+     * @see Status
+     */
+    /** {@hide} */
+    public int status;
+
+    /**
+     * The network's SSID. Can either be an ASCII string,
+     * which must be enclosed in double quotation marks
+     * (e.g., {@code "MyNetwork"}, or a string of
+     * hex digits,which are not enclosed in quotes
+     * (e.g., {@code 01a243f405}).
+     */
+    /** {@hide} */
+    public String SSID;
+    /**
+     * When set. this is the BSSID the radio is currently associated with.
+     * The value is a string in the format of an Ethernet MAC address, e.g.,
+     * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
+     */
+    /** {@hide} */
+    public String BSSID;
+
+    /* number beacons received from our own AP */
+    /** {@hide} */
+    public int beacon_rx;
+
+    /* RSSI taken on management frames */
+    /** {@hide} */
+    public int rssi_mgmt;
+
+    /* packets counters */
+    /** {@hide} */
+    /* WME Best Effort Access Category (receive mpdu, transmit mpdu, lost mpdu, number of retries)*/
+    public long rxmpdu_be;
+    /** {@hide} */
+    public long txmpdu_be;
+    /** {@hide} */
+    public long lostmpdu_be;
+    /** {@hide} */
+    public long retries_be;
+    /** {@hide} */
+    /* WME Background Access Category (receive mpdu, transmit mpdu, lost mpdu, number of retries) */
+    public long rxmpdu_bk;
+    /** {@hide} */
+    public long txmpdu_bk;
+    /** {@hide} */
+    public long lostmpdu_bk;
+    /** {@hide} */
+    public long retries_bk;
+    /** {@hide} */
+    /* WME Video Access Category (receive mpdu, transmit mpdu, lost mpdu, number of retries) */
+    public long rxmpdu_vi;
+    /** {@hide} */
+    public long txmpdu_vi;
+    /** {@hide} */
+    public long lostmpdu_vi;
+    /** {@hide} */
+    public long retries_vi;
+    /** {@hide} */
+    /* WME Voice Access Category (receive mpdu, transmit mpdu, lost mpdu, number of retries) */
+    public long rxmpdu_vo;
+    /** {@hide} */
+    public long txmpdu_vo;
+    /** {@hide} */
+    public long lostmpdu_vo;
+    /** {@hide} */
+    public long retries_vo;
+
+
+    /** {@hide} */
+    public WifiLinkLayerStats() {
+    }
+
+    @Override
+    /** {@hide} */
+    public String toString() {
+        StringBuilder sbuf = new StringBuilder();
+        if (this.SSID != null) {
+            sbuf.append(" SSID: ").append(this.SSID).append('\n');
+        }
+        if (this.BSSID != null) {
+            sbuf.append(" BSSID: ").append(this.BSSID).append('\n');
+        }
+
+        sbuf.append(" my bss beacon rx: ").append(Integer.toString(this.beacon_rx)).append('\n');
+        sbuf.append(" RSSI mgmt: ").append(Integer.toString(this.rssi_mgmt)).append('\n');
+        sbuf.append(" BE : ").append(" rx=").append(Long.toString(this.rxmpdu_be))
+                .append(" tx=").append(Long.toString(this.txmpdu_be))
+                .append(" lost=").append(Long.toString(this.lostmpdu_be))
+                .append(" retries=").append(Long.toString(this.retries_be)).append('\n');
+        sbuf.append(" BK : ").append(" rx=").append(Long.toString(this.rxmpdu_bk))
+                .append(" tx=").append(Long.toString(this.txmpdu_bk))
+                .append(" lost=").append(Long.toString(this.lostmpdu_bk))
+                .append(" retries=").append(Long.toString(this.retries_bk)).append('\n');
+        sbuf.append(" VI : ").append(" rx=").append(Long.toString(this.rxmpdu_vi))
+                .append(" tx=").append(Long.toString(this.txmpdu_vi))
+                .append(" lost=").append(Long.toString(this.lostmpdu_vi))
+                .append(" retries=").append(Long.toString(this.retries_vi)).append('\n');
+        sbuf.append(" VO : ").append(" rx=").append(Long.toString(this.rxmpdu_vo))
+                .append(" tx=").append(Long.toString(this.txmpdu_vo))
+                .append(" lost=").append(Long.toString(this.lostmpdu_vo))
+                .append(" retries=").append(Long.toString(this.retries_vo)).append('\n');
+
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** {@hide} */
+    public String getPrintableSsid() {
+        if (SSID == null) return "";
+        final int length = SSID.length();
+        if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') {
+            return SSID.substring(1, length - 1);
+        }
+
+        /** The ascii-encoded string format is P"<ascii-encoded-string>"
+         * The decoding is implemented in the supplicant for a newly configured
+         * network.
+         */
+        if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') &&
+                (SSID.charAt(length-1) == '"')) {
+            WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(
+                    SSID.substring(2, length - 1));
+            return wifiSsid.toString();
+        }
+        return SSID;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(SSID);
+        dest.writeString(BSSID);
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiLinkLayerStats> CREATOR =
+        new Creator<WifiLinkLayerStats>() {
+            public WifiLinkLayerStats createFromParcel(Parcel in) {
+                WifiLinkLayerStats stats = new WifiLinkLayerStats();
+                stats.SSID = in.readString();
+                stats.BSSID = in.readString();
+                return stats;
+            };
+            public WifiLinkLayerStats[] newArray(int size) {
+                return new WifiLinkLayerStats[size];
+            }
+
+        };
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 15b65c1..9558d50 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1783,18 +1783,6 @@
         }
     }
 
-    /**
-     * Get a reference to WifiStateMachine handler.
-     * @return Messenger pointing to the WifiService handler
-     * @hide
-     */
-    public Messenger getWifiStateMachineMessenger() {
-        try {
-            return mService.getWifiStateMachineMessenger();
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
 
     /**
      * Returns the file in which IP and proxy configuration data is stored
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index e02e14c..b766268 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -31,7 +31,6 @@
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
@@ -41,27 +40,45 @@
  * Get an instance of this class by calling
  * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context
  * .WIFI_SCANNING_SERVICE)}.
- * @hide
  */
 public class WifiScanner {
 
+    /** no band specified; use channel list instead */
     public static final int WIFI_BAND_UNSPECIFIED = 0;      /* not specified */
+
+    /** 2.4 GHz band */
     public static final int WIFI_BAND_24_GHZ = 1;           /* 2.4 GHz band */
+    /** 5 GHz band excluding DFS channels */
     public static final int WIFI_BAND_5_GHZ = 2;            /* 5 GHz band without DFS channels */
+    /** DFS channels from 5 GHz band only */
     public static final int WIFI_BAND_5_GHZ_DFS_ONLY  = 4;  /* 5 GHz band with DFS channels */
+    /** 5 GHz band including DFS channels */
     public static final int WIFI_BAND_5_GHZ_WITH_DFS  = 6;  /* 5 GHz band with DFS channels */
+    /** Both 2.4 GHz band and 5 GHz band; no DFS channels */
     public static final int WIFI_BAND_BOTH = 3;             /* both bands without DFS channels */
+    /** Both 2.4 GHz band and 5 GHz band; with DFS channels */
     public static final int WIFI_BAND_BOTH_WITH_DFS = 7;    /* both bands with DFS channels */
 
-    public static final int MIN_SCAN_PERIOD_MS = 300;       /* minimum supported period */
+    /** Minimum supported scanning period */
+    public static final int MIN_SCAN_PERIOD_MS = 2000;      /* minimum supported period */
+    /** Maximum supported scanning period */
     public static final int MAX_SCAN_PERIOD_MS = 1024000;   /* maximum supported period */
 
+    /** No Error */
     public static final int REASON_SUCCEEDED = 0;
+    /** Unknown error */
     public static final int REASON_UNSPECIFIED = -1;
+    /** Invalid listener */
     public static final int REASON_INVALID_LISTENER = -2;
+    /** Invalid request */
     public static final int REASON_INVALID_REQUEST = -3;
+    /** Request conflicts with other scans that may be going on */
     public static final int REASON_CONFLICTING_REQUEST = -4;
 
+    /**
+     * Generic action callback invocation interface
+     *  @hide
+     */
     public static interface ActionListener {
         public void onSuccess(Object result);
         public void onFailure(int reason, Object exception);
@@ -70,19 +87,35 @@
     /**
      * gives you all the possible channels; channel is specified as an
      * integer with frequency in MHz i.e. channel 1 is 2412
+     * @hide
      */
     public List<Integer> getAvailableChannels(int band) {
         return null;
     }
 
     /**
-     * provides channel specification to the APIs
+     * provides channel specification for scanning
      */
     public static class ChannelSpec {
+        /**
+         * channel frequency in KHz; for example channel 1 is specified as 2412
+         */
         public int frequency;
+        /**
+         * if true, scan this channel in passive fashion.
+         * This flag is ignored on DFS channel specification.
+         * @hide
+         */
         public boolean passive;                                    /* ignored on DFS channels */
+        /**
+         * how long to dwell on this channel
+         * @hide
+         */
         public int dwellTimeMS;                                    /* not supported for now */
 
+        /**
+         * default constructor for channel spec
+         */
         public ChannelSpec(int frequency) {
             this.frequency = frequency;
             passive = false;
@@ -90,19 +123,26 @@
         }
     }
 
+    /** reports {@link ScanListener#onResults} when underlying buffers are full */
     public static final int REPORT_EVENT_AFTER_BUFFER_FULL = 0;
+    /** reports {@link ScanListener#onResults} after each scan */
     public static final int REPORT_EVENT_AFTER_EACH_SCAN = 1;
+    /** reports {@link ScanListener#onFullResult} whenever each beacon is discovered */
     public static final int REPORT_EVENT_FULL_SCAN_RESULT = 2;
 
     /**
-     * scan configuration parameters
+     * scan configuration parameters to be sent to {@link #startBackgroundScan}
      */
     public static class ScanSettings implements Parcelable {
 
-        public int band;                                           /* ignore channels if specified */
-        public ChannelSpec[] channels;                             /* list of channels to scan */
-        public int periodInMs;                                     /* period of scan */
-        public int reportEvents;                                   /* a valid REPORT_EVENT value */
+        /** one of the WIFI_BAND values */
+        public int band;
+        /** list of channels; used when band is set to WIFI_BAND_UNSPECIFIED */
+        public ChannelSpec[] channels;
+        /** period of background scan; in millisecond */
+        public int periodInMs;
+        /** must have a valid REPORT_EVENT value */
+        public int reportEvents;
 
         /** Implement the Parcelable interface {@hide} */
         public int describeContents() {
@@ -113,6 +153,7 @@
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(band);
             dest.writeInt(periodInMs);
+            dest.writeInt(reportEvents);
             dest.writeInt(channels.length);
 
             for (int i = 0; i < channels.length; i++) {
@@ -130,6 +171,7 @@
                         ScanSettings settings = new ScanSettings();
                         settings.band = in.readInt();
                         settings.periodInMs = in.readInt();
+                        settings.reportEvents = in.readInt();
                         int num_channels = in.readInt();
                         settings.channels = new ChannelSpec[num_channels];
                         for (int i = 0; i < num_channels; i++) {
@@ -151,14 +193,56 @@
 
     }
 
+    /** information element from beacon */
     public static class InformationElement {
         public int id;
         public byte[] bytes;
     }
 
-    public static class FullScanResult {
+    /** scan result with information elements from beacons */
+    public static class FullScanResult implements Parcelable {
         public ScanResult result;
         public InformationElement informationElements[];
+
+        /** Implement the Parcelable interface {@hide} */
+        public int describeContents() {
+            return 0;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public void writeToParcel(Parcel dest, int flags) {
+            result.writeToParcel(dest, flags);
+            dest.writeInt(informationElements.length);
+            for (int i = 0; i < informationElements.length; i++) {
+                dest.writeInt(informationElements[i].id);
+                dest.writeInt(informationElements[i].bytes.length);
+                dest.writeByteArray(informationElements[i].bytes);
+            }
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public static final Creator<FullScanResult> CREATOR =
+                new Creator<FullScanResult>() {
+                    public FullScanResult createFromParcel(Parcel in) {
+                        FullScanResult result = new FullScanResult();
+                        result.result = ScanResult.CREATOR.createFromParcel(in);
+                        int n = in.readInt();
+                        result.informationElements = new InformationElement[n];
+                        for (int i = 0; i < n; i++) {
+                            result.informationElements[i] = new InformationElement();
+                            result.informationElements[i].id = in.readInt();
+                            int len = in.readInt();
+                            result.informationElements[i].bytes = new byte[len];
+                            in.readByteArray(result.informationElements[i].bytes);
+                        }
+
+                        return result;
+                    }
+
+                    public FullScanResult[] newArray(int size) {
+                        return new FullScanResult[size];
+                    }
+                };
     }
 
     /** @hide */
@@ -206,88 +290,210 @@
     }
 
     /**
-     * Framework is co-ordinating scans across multiple apps; so it may not give exactly the
-     * same period requested. The period granted is stated on the onSuccess() event; and
-     * onPeriodChanged() will be called if/when it is changed because of multiple conflicting
-     * requests. This is similar to the way timers are handled.
+     * interface to get scan events on; specify this on {@link #startBackgroundScan}
      */
     public interface ScanListener extends ActionListener {
+        /**
+         * Framework co-ordinates scans across multiple apps; so it may not give exactly the
+         * same period requested. If period of a scan is changed; it is reported by this event.
+         */
         public void onPeriodChanged(int periodInMs);
+        /**
+         * reports results retrieved from background scan
+         */
         public void onResults(ScanResult[] results);
+        /**
+         * reports full scan result for each access point found in scan
+         */
         public void onFullResult(FullScanResult fullScanResult);
     }
 
+    /** @hide */
     public void scan(ScanSettings settings, ScanListener listener) {
         validateChannel();
         sAsyncChannel.sendMessage(CMD_SCAN, 0, putListener(listener), settings);
     }
+
+    /** start wifi scan in background
+     * @param settings specifies various parameters for the scan; for more information look at
+     * {@link ScanSettings}
+     * @param listener specifies the object to report events to. This object is also treated as a
+     *                 key for this scan, and must also be specified to cancel the scan. Multiple
+     *                 scans should also not share this object.
+     */
     public void startBackgroundScan(ScanSettings settings, ScanListener listener) {
         validateChannel();
         sAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, putListener(listener), settings);
     }
-    public void stopBackgroundScan(boolean flush, ScanListener listener) {
+    /**
+     * stop an ongoing wifi scan
+     * @param listener specifies which scan to cancel; must be same object as passed in {@link
+     *  #startBackgroundScan}
+     */
+    public void stopBackgroundScan(ScanListener listener) {
         validateChannel();
         sAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, removeListener(listener));
     }
+    /**
+     * retrieves currently available scan results
+     * @param flush {@code true} means flush all results
+     * @param listener specifies which scan to cancel; must be same object as passed in {@link
+     *                 #startBackgroundScan}
+     */
     public void retrieveScanResults(boolean flush, ScanListener listener) {
         validateChannel();
         sAsyncChannel.sendMessage(CMD_GET_SCAN_RESULTS, 0, getListenerKey(listener));
     }
 
+    /** specifies information about an access point of interest */
     public static class HotspotInfo {
+        /** bssid of the access point; in XX:XX:XX:XX:XX:XX format */
         public String bssid;
+        /** low signal strength threshold; more information at {@link ScanResult#level} */
         public int low;                                            /* minimum RSSI */
+        /** high signal threshold; more information at {@link ScanResult#level} */
         public int high;                                           /* maximum RSSI */
+        /** channel frequency (in KHz) where you may find this BSSID */
+        public int frequencyHint;
     }
 
-    public static class WifiChangeSettings {
-        public int rssiSampleSize;                                 /* sample size for RSSI averaging */
-        public int lostApSampleSize;                               /* samples to confirm AP's loss */
-        public int unchangedSampleSize;                            /* samples to confirm no change */
-        public int minApsBreachingThreshold;                       /* change threshold to trigger event */
+    /** @hide */
+    public static class WifiChangeSettings implements Parcelable {
+        public int rssiSampleSize;                          /* sample size for RSSI averaging */
+        public int lostApSampleSize;                        /* samples to confirm AP's loss */
+        public int unchangedSampleSize;                     /* samples to confirm no change */
+        public int minApsBreachingThreshold;                /* change threshold to trigger event */
+        public int periodInMs;                              /* scan period in millisecond */
         public HotspotInfo[] hotspotInfos;
+
+        /** Implement the Parcelable interface {@hide} */
+        public int describeContents() {
+            return 0;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(rssiSampleSize);
+            dest.writeInt(lostApSampleSize);
+            dest.writeInt(unchangedSampleSize);
+            dest.writeInt(minApsBreachingThreshold);
+            dest.writeInt(periodInMs);
+            dest.writeInt(hotspotInfos.length);
+            for (int i = 0; i < hotspotInfos.length; i++) {
+                HotspotInfo info = hotspotInfos[i];
+                dest.writeString(info.bssid);
+                dest.writeInt(info.low);
+                dest.writeInt(info.high);
+                dest.writeInt(info.frequencyHint);
+            }
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public static final Creator<WifiChangeSettings> CREATOR =
+                new Creator<WifiChangeSettings>() {
+                    public WifiChangeSettings createFromParcel(Parcel in) {
+                        WifiChangeSettings settings = new WifiChangeSettings();
+                        settings.rssiSampleSize = in.readInt();
+                        settings.lostApSampleSize = in.readInt();
+                        settings.unchangedSampleSize = in.readInt();
+                        settings.minApsBreachingThreshold = in.readInt();
+                        settings.periodInMs = in.readInt();
+                        int len = in.readInt();
+                        settings.hotspotInfos = new HotspotInfo[len];
+                        for (int i = 0; i < len; i++) {
+                            HotspotInfo info = new HotspotInfo();
+                            info.bssid = in.readString();
+                            info.low = in.readInt();
+                            info.high = in.readInt();
+                            info.frequencyHint = in.readInt();
+                            settings.hotspotInfos[i] = info;
+                        }
+                        return settings;
+                    }
+
+                    public WifiChangeSettings[] newArray(int size) {
+                        return new WifiChangeSettings[size];
+                    }
+                };
+
     }
 
-    /* overrides the significant wifi change state machine configuration */
-    public void configureSignificantWifiChange(
+    /** configure WifiChange detection
+     * @param rssiSampleSize number of samples used for RSSI averaging
+     * @param lostApSampleSize number of samples to confirm an access point's loss
+     * @param unchangedSampleSize number of samples to confirm there are no changes
+     * @param minApsBreachingThreshold minimum number of access points that need to be
+     *                                 out of range to detect WifiChange
+     * @param periodInMs indicates period of scan to find changes
+     * @param hotspotInfos access points to watch
+     */
+    public void configureWifiChange(
             int rssiSampleSize,                             /* sample size for RSSI averaging */
             int lostApSampleSize,                           /* samples to confirm AP's loss */
             int unchangedSampleSize,                        /* samples to confirm no change */
             int minApsBreachingThreshold,                   /* change threshold to trigger event */
+            int periodInMs,                                 /* period of scan */
             HotspotInfo[] hotspotInfos                      /* signal thresholds to crosss */
             )
     {
         validateChannel();
+
         WifiChangeSettings settings = new WifiChangeSettings();
         settings.rssiSampleSize = rssiSampleSize;
         settings.lostApSampleSize = lostApSampleSize;
         settings.unchangedSampleSize = unchangedSampleSize;
         settings.minApsBreachingThreshold = minApsBreachingThreshold;
+        settings.periodInMs = periodInMs;
         settings.hotspotInfos = hotspotInfos;
 
-        sAsyncChannel.sendMessage(CMD_CONFIGURE_WIFI_CHANGE, 0, 0, settings);
+        configureWifiChange(settings);
     }
 
-    public interface SignificantWifiChangeListener extends ActionListener {
+    /**
+     * interface to get wifi change events on; use this on {@link #startTrackingWifiChange}
+     */
+    public interface WifiChangeListener extends ActionListener {
+        /** indicates that changes were detected in wifi environment
+         * @param results indicate the access points that exhibited change
+         */
         public void onChanging(ScanResult[] results);           /* changes are found */
+        /** indicates that no wifi changes are being detected for a while
+         * @param results indicate the access points that are bing monitored for change
+         */
         public void onQuiescence(ScanResult[] results);         /* changes settled down */
     }
 
-    public void trackSignificantWifiChange(SignificantWifiChangeListener listener) {
+    /**
+     * track changes in wifi environment
+     * @param listener object to report events on; this object must be unique and must also be
+     *                 provided on {@link #stopTrackingWifiChange}
+     */
+    public void startTrackingWifiChange(WifiChangeListener listener) {
         validateChannel();
         sAsyncChannel.sendMessage(CMD_START_TRACKING_CHANGE, 0, putListener(listener));
     }
-    public void untrackSignificantWifiChange(SignificantWifiChangeListener listener) {
+
+    /**
+     * stop tracking changes in wifi environment
+     * @param listener object that was provided to report events on {@link
+     * #stopTrackingWifiChange}
+     */
+    public void stopTrackingWifiChange(WifiChangeListener listener) {
         validateChannel();
         sAsyncChannel.sendMessage(CMD_STOP_TRACKING_CHANGE, 0, removeListener(listener));
     }
 
-    public void configureSignificantWifiChange(WifiChangeSettings settings) {
+    /** @hide */
+    public void configureWifiChange(WifiChangeSettings settings) {
         validateChannel();
         sAsyncChannel.sendMessage(CMD_CONFIGURE_WIFI_CHANGE, 0, 0, settings);
     }
 
+    /** interface to receive hotlist events on; use this on {@link #setHotlist} */
     public static interface HotlistListener extends ActionListener {
+        /** indicates that access points were found by on going scans
+         * @param results list of scan results, one for each access point visible currently
+         */
         public void onFound(ScanResult[] results);
     }
 
@@ -310,6 +516,7 @@
                 dest.writeString(info.bssid);
                 dest.writeInt(info.low);
                 dest.writeInt(info.high);
+                dest.writeInt(info.frequencyHint);
             }
         }
 
@@ -326,6 +533,7 @@
                             info.bssid = in.readString();
                             info.low = in.readInt();
                             info.high = in.readInt();
+                            info.frequencyHint = in.readInt();
                             settings.hotspotInfos[i] = info;
                         }
                         return settings;
@@ -337,6 +545,13 @@
                 };
     }
 
+    /**
+     * set interesting access points to find
+     * @param hotspots access points of interest
+     * @param apLostThreshold number of scans needed to indicate that AP is lost
+     * @param listener object provided to report events on; this object must be unique and must
+     *                 also be provided on {@link #resetHotlist}
+     */
     public void setHotlist(HotspotInfo[] hotspots,
             int apLostThreshold, HotlistListener listener) {
         validateChannel();
@@ -345,6 +560,10 @@
         sAsyncChannel.sendMessage(CMD_SET_HOTLIST, 0, putListener(listener), settings);
     }
 
+    /**
+     * remove tracking of interesting access points
+     * @param listener same object provided in {@link #setHotlist}
+     */
     public void resetHotlist(HotlistListener listener) {
         validateChannel();
         sAsyncChannel.sendMessage(CMD_RESET_HOTLIST, 0, removeListener(listener));
@@ -554,6 +773,7 @@
                     break;
                 case CMD_OP_FAILED :
                     ((ActionListener) listener).onFailure(msg.arg1, msg.obj);
+                    removeListener(msg.arg2);
                     break;
                 case CMD_SCAN_RESULT :
                     ((ScanListener) listener).onResults(
@@ -568,11 +788,11 @@
                             ((ParcelableScanResults) msg.obj).getResults());
                     return;
                 case CMD_WIFI_CHANGE_DETECTED:
-                    ((SignificantWifiChangeListener) listener).onChanging(
+                    ((WifiChangeListener) listener).onChanging(
                             ((ParcelableScanResults) msg.obj).getResults());
                    return;
                 case CMD_WIFI_CHANGES_STABILIZED:
-                    ((SignificantWifiChangeListener) listener).onQuiescence(
+                    ((WifiChangeListener) listener).onQuiescence(
                             ((ParcelableScanResults) msg.obj).getResults());
                     return;
                 default:
diff --git a/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java b/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java
deleted file mode 100644
index ac15017..0000000
--- a/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.hotspot;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * TODO: doc
- */
-public class WifiHotspotManager {
-
-    private static final String TAG = "WifiHotspotManager";
-
-    private Context mContext;
-    IWifiHotspotManager mService;
-
-    public WifiHotspotManager(Context context, IWifiHotspotManager service) {
-        mContext = context;
-        mService = service;
-    }
-
-    public void test() {
-        try{
-            Log.d(TAG, "test()");
-            mService.test();
-        }
-        catch (RemoteException e) {
-            Log.e(TAG, "test() exception");
-            e.printStackTrace();
-        }
-    }
-}
diff --git a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl b/wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl
similarity index 73%
copy from wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
copy to wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl
index 2b1601b..e57db64 100644
--- a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl
@@ -14,15 +14,18 @@
  * limitations under the License.
  */
 
-package android.net.wifi.hotspot;
+package android.net.wifi.passpoint;
+
+import android.os.Messenger;
 
 /**
- * Interface that allows controlling and querying Hotspot connectivity.
+ * Interface that allows controlling and querying Passpoint connectivity.
  *
  * {@hide}
  */
-interface IWifiHotspotManager
+interface IPasspointManager
 {
-    void test();
+    Messenger getMessenger();
+    int getPasspointState();
 }
 
diff --git a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl b/wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl
similarity index 77%
rename from wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
rename to wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl
index 2b1601b..6f75cbe 100644
--- a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl
@@ -14,15 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.hotspot;
+package android.net.wifi.passpoint;
 
-/**
- * Interface that allows controlling and querying Hotspot connectivity.
- *
- * {@hide}
- */
-interface IWifiHotspotManager
-{
-    void test();
-}
-
+parcelable PasspointCredential;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointCredential.java b/wifi/java/android/net/wifi/passpoint/PasspointCredential.java
new file mode 100644
index 0000000..4218f23
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/PasspointCredential.java
@@ -0,0 +1,56 @@
+/*
+ * 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.net.wifi.passpoint;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+public class PasspointCredential implements Parcelable {
+
+    @Override
+    public String toString() {
+        // TODO
+        return null;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        // TODO
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<PasspointCredential> CREATOR =
+            new Creator<PasspointCredential>() {
+                @Override
+                public PasspointCredential createFromParcel(Parcel in) {
+                    // TODO
+                    return null;
+                }
+
+                @Override
+                public PasspointCredential[] newArray(int size) {
+                    return new PasspointCredential[size];
+                }
+            };
+}
diff --git a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl b/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
similarity index 77%
copy from wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
copy to wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
index 2b1601b..cc11045 100644
--- a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
@@ -14,15 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.hotspot;
+package android.net.wifi.passpoint;
 
-/**
- * Interface that allows controlling and querying Hotspot connectivity.
- *
- * {@hide}
- */
-interface IWifiHotspotManager
-{
-    void test();
-}
-
+parcelable PasspointInfo;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointInfo.java b/wifi/java/android/net/wifi/passpoint/PasspointInfo.java
new file mode 100644
index 0000000..d57b0aa
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/PasspointInfo.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * TODO: doc
+ */
+public class PasspointInfo implements Parcelable {
+
+    /** TODO doc */
+    public static final int ANQP_CAPABILITY             = 1 << 0;
+
+    /** TODO doc */
+    public static final int VENUE_NAME                  = 1 << 1;
+
+    /** TODO doc */
+    public static final int NETWORK_AUTH_TYPE           = 1 << 2;
+
+    /** TODO doc */
+    public static final int ROAMING_CONSORTIUM          = 1 << 3;
+
+    /** TODO doc */
+    public static final int IP_ADDR_TYPE_AVAILABILITY   = 1 << 4;
+
+    /** TODO doc */
+    public static final int NAI_REALM                   = 1 << 5;
+
+    /** TODO doc */
+    public static final int CELLULAR_NETWORK            = 1 << 6;
+
+    /** TODO doc */
+    public static final int DOMAIN_NAME                 = 1 << 7;
+
+    /** TODO doc */
+    public static final int HOTSPOT_CAPABILITY          = 1 << 8;
+
+    /** TODO doc */
+    public static final int OPERATOR_FRIENDLY_NAME      = 1 << 9;
+
+    /** TODO doc */
+    public static final int WAN_METRICS                 = 1 << 10;
+
+    /** TODO doc */
+    public static final int CONNECTION_CAPABILITY       = 1 << 11;
+
+    /** TODO doc */
+    public static final int OSU_PROVIDER                = 1 << 12;
+
+    /** TODO doc */
+    public static final int PRESET_CRED_MATCH =
+            ANQP_CAPABILITY |
+            HOTSPOT_CAPABILITY |
+            NAI_REALM |
+            CELLULAR_NETWORK |
+            DOMAIN_NAME;
+
+    /** TODO doc */
+    public static final int PRESET_ALL =
+            ANQP_CAPABILITY |
+            VENUE_NAME |
+            NETWORK_AUTH_TYPE |
+            ROAMING_CONSORTIUM |
+            IP_ADDR_TYPE_AVAILABILITY |
+            NAI_REALM |
+            CELLULAR_NETWORK |
+            DOMAIN_NAME |
+            HOTSPOT_CAPABILITY |
+            OPERATOR_FRIENDLY_NAME |
+            WAN_METRICS |
+            CONNECTION_CAPABILITY |
+            OSU_PROVIDER;
+
+
+    /** TODO doc */
+    public String bssid;
+
+    /** TODO doc */
+    public String venueName;
+
+    /** TODO doc */
+    public String networkAuthType;
+
+    /** TODO doc */
+    public String roamingConsortium;
+
+    /** TODO doc */
+    public String ipAddrTypeAvaibility;
+
+    /** TODO doc */
+    public String naiRealm;
+
+    /** TODO doc */
+    public String cellularNetwork;
+
+    /** TODO doc */
+    public String domainName;
+
+    /** TODO doc */
+    public String operatorFriendlyName;
+
+    /** TODO doc */
+    public String wanMetrics;
+
+    /** TODO doc */
+    public String connectionCapability;
+
+    /** TODO doc */
+    public List<PasspointOsuProvider> osuProviderList;
+
+
+    /** default constructor @hide */
+    public PasspointInfo() {
+//        osuProviderList = new ArrayList<OsuProvider>();
+    }
+
+    /** copy constructor @hide */
+    public PasspointInfo(PasspointInfo source) {
+        // TODO
+        bssid = source.bssid;
+        venueName = source.venueName;
+        networkAuthType = source.networkAuthType;
+        roamingConsortium = source.roamingConsortium;
+        ipAddrTypeAvaibility = source.ipAddrTypeAvaibility;
+        naiRealm = source.naiRealm;
+        cellularNetwork = source.cellularNetwork;
+        domainName = source.domainName;
+        operatorFriendlyName = source.operatorFriendlyName;
+        wanMetrics = source.wanMetrics;
+        connectionCapability = source.connectionCapability;
+        if (source.osuProviderList != null) {
+            osuProviderList = new ArrayList<PasspointOsuProvider>();
+            for (PasspointOsuProvider osu : source.osuProviderList)
+                osuProviderList.add(new PasspointOsuProvider(osu));
+        }
+    }
+
+    /**
+     * Convert mask to ANQP subtypes, for supplicant command use.
+     *
+     * @param mask The ANQP subtypes mask.
+     * @return String of ANQP subtypes, good for supplicant command use
+     * @hide
+     */
+    public static String toAnqpSubtypes(int mask) {
+        StringBuilder sb = new StringBuilder();
+        if ((mask & ANQP_CAPABILITY) != 0) sb.append("257,");
+        if ((mask & VENUE_NAME) != 0) sb.append("258,");
+        if ((mask & NETWORK_AUTH_TYPE) != 0) sb.append("260,");
+        if ((mask & ROAMING_CONSORTIUM) != 0) sb.append("261,");
+        if ((mask & IP_ADDR_TYPE_AVAILABILITY) != 0) sb.append("262,");
+        if ((mask & NAI_REALM) != 0) sb.append("263,");
+        if ((mask & CELLULAR_NETWORK) != 0) sb.append("264,");
+        if ((mask & DOMAIN_NAME) != 0) sb.append("268,");
+        if ((mask & HOTSPOT_CAPABILITY) != 0) sb.append("hs20:2,");
+        if ((mask & OPERATOR_FRIENDLY_NAME) != 0) sb.append("hs20:3,");
+        if ((mask & WAN_METRICS) != 0) sb.append("hs20:4,");
+        if ((mask & CONNECTION_CAPABILITY) != 0) sb.append("hs20:5,");
+        if ((mask & OSU_PROVIDER) != 0) sb.append("hs20:8,");
+        if (sb.length() > 0) sb.deleteCharAt(sb.length() - 1);
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("BSSID: ").append(bssid);
+        if (venueName != null)
+            sb.append(" venueName: ").append(venueName);
+        if (networkAuthType != null)
+            sb.append(" networkAuthType: ").append(networkAuthType);
+        if (roamingConsortium != null)
+            sb.append(" roamingConsortium: ").append(roamingConsortium);
+        if (ipAddrTypeAvaibility != null)
+            sb.append(" ipAddrTypeAvaibility: ").append(ipAddrTypeAvaibility);
+        if (naiRealm != null)
+            sb.append(" naiRealm: ").append(naiRealm);
+        if (cellularNetwork != null)
+            sb.append(" cellularNetwork: ").append(cellularNetwork);
+        if (domainName != null)
+            sb.append(" domainName: ").append(domainName);
+        if (operatorFriendlyName != null)
+            sb.append(" operatorFriendlyName: ").append(operatorFriendlyName);
+        if (wanMetrics != null)
+            sb.append(" wanMetrics: ").append(wanMetrics);
+        if (connectionCapability != null)
+            sb.append(" connectionCapability: ").append(connectionCapability);
+        if (osuProviderList != null)
+            sb.append(" osuProviderList: (size=" + osuProviderList.size() + ")");
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeValue(bssid);
+        out.writeValue(venueName);
+        out.writeValue(networkAuthType);
+        out.writeValue(roamingConsortium);
+        out.writeValue(ipAddrTypeAvaibility);
+        out.writeValue(naiRealm);
+        out.writeValue(cellularNetwork);
+        out.writeValue(domainName);
+        out.writeValue(operatorFriendlyName);
+        out.writeValue(wanMetrics);
+        out.writeValue(connectionCapability);
+        if (osuProviderList == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(osuProviderList.size());
+            for (PasspointOsuProvider osu : osuProviderList)
+                osu.writeToParcel(out, flags);
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Parcelable.Creator<PasspointInfo> CREATOR =
+            new Parcelable.Creator<PasspointInfo>() {
+        @Override
+        public PasspointInfo createFromParcel(Parcel in) {
+            PasspointInfo p = new PasspointInfo();
+            p.bssid = (String) in.readValue(String.class.getClassLoader());
+            p.venueName = (String) in.readValue(String.class.getClassLoader());
+            p.networkAuthType = (String) in.readValue(String.class.getClassLoader());
+            p.roamingConsortium = (String) in.readValue(String.class.getClassLoader());
+            p.ipAddrTypeAvaibility = (String) in.readValue(String.class.getClassLoader());
+            p.naiRealm = (String) in.readValue(String.class.getClassLoader());
+            p.cellularNetwork = (String) in.readValue(String.class.getClassLoader());
+            p.domainName = (String) in.readValue(String.class.getClassLoader());
+            p.operatorFriendlyName = (String) in.readValue(String.class.getClassLoader());
+            p.wanMetrics = (String) in.readValue(String.class.getClassLoader());
+            p.connectionCapability = (String) in.readValue(String.class.getClassLoader());
+            int n = in.readInt();
+            if (n > 0) {
+                p.osuProviderList = new ArrayList<PasspointOsuProvider>();
+                for (int i = 0; i < n; i++) {
+                    PasspointOsuProvider osu = PasspointOsuProvider.CREATOR.createFromParcel(in);
+                    p.osuProviderList.add(osu);
+                }
+            }
+            return p;
+        }
+
+        @Override
+        public PasspointInfo[] newArray(int size) {
+            return new PasspointInfo[size];
+        }
+    };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointManager.java b/wifi/java/android/net/wifi/passpoint/PasspointManager.java
new file mode 100644
index 0000000..234a44c
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/PasspointManager.java
@@ -0,0 +1,504 @@
+/*
+ * 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.net.wifi.passpoint;
+
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * TODO: doc
+ */
+public class PasspointManager {
+
+    private static final String TAG = "PasspointManager";
+
+    private static final boolean DBG = true;
+
+    /* Passpoint states values */
+
+    /** Passpoint is in an known state. This should only occur in boot time */
+    public static final int PASSPOINT_STATE_UNKNOWN     = 0;
+
+    /** Passpoint is disabled. This occurs when wifi is disabled. */
+    public static final int PASSPOINT_STATE_DISABLED    = 1;
+
+    /** Passpoint is enabled and in discovery state. */
+    public static final int PASSPOINT_STATE_DISCOVERY   = 2;
+
+    /** Passpoint is enabled and in access state. */
+    public static final int PASSPOINT_STATE_ACCESS      = 3;
+
+    /** Passpoint is enabled and in provisioning state. */
+    public static final int PASSPOINT_STATE_PROVISION   = 4;
+
+    /* Passpoint callback error codes */
+
+    /** Indicates that the operation failed due to an internal error */
+    public static final int ERROR           = 0;
+
+    /** Indicates that the operation failed because wifi is disabled */
+    public static final int WIFI_DISABLED   = 1;
+
+    /** Indicates that the operation failed because the framework is busy */
+    public static final int BUSY            = 2;
+
+    /* Passpoint broadcasts */
+
+    /**
+     * Broadcast intent action indicating that the state of Passpoint
+     * connectivity has changed
+     */
+    public static final String PASSPOINT_STATE_CHANGED_ACTION =
+            "android.net.wifi.passpoint.STATE_CHANGE";
+
+    /**
+     * Broadcast intent action indicating that the saved Passpoint credential
+     * list has changed
+     */
+    public static final String PASSPOINT_CRED_CHANGED_ACTION =
+            "android.net.wifi.passpoint.CRED_CHANGE";
+
+    /**
+     * Broadcast intent action indicating that Passpoint online sign up is
+     * avaiable.
+     * @hide
+     */
+    public static final String PASSPOINT_OSU_AVAILABLE_ACTION =
+            "android.net.wifi.passpoint.OSU_AVAILABLE";
+
+    /**
+     * Broadcast intent action indicating that user remediation is required
+     * @hide
+     */
+    public static final String PASSPOINT_USER_REM_REQ_ACTION =
+            "android.net.wifi.passpoint.USER_REM_REQ";
+
+
+    /**
+     * Interface for callback invocation when framework channel is lost
+     */
+    public interface ChannelListener {
+        /**
+         * The channel to the framework has been disconnected. Application could
+         * try re-initializing using {@link #initialize}
+         */
+        public void onChannelDisconnected();
+    }
+
+    /**
+     * Interface for callback invocation on an application action
+     */
+    public interface ActionListener {
+        /** The operation succeeded */
+        public void onSuccess();
+
+        /**
+         * * The operation failed
+         *
+         * @param reason The reason for failure could be one of
+         *            {@link #WIFI_DISABLED}, {@link #ERROR} or {@link #BUSY}
+         */
+        public void onFailure(int reason);
+    }
+
+    /**
+     * Interface for callback invocation when doing OSU or user remediation
+     * @hide
+     */
+    public interface OsuRemListener {
+        /** The operation succeeded */
+        public void onSuccess();
+
+        /**
+         * The operation failed
+         *
+         * @param reason The reason for failure could be one of
+         *            {@link #WIFI_DISABLED}, {@link #ERROR} or {@link #BUSY}
+         */
+        public void onFailure(int reason);
+
+        /**
+         * Browser launch is requried for user interaction. When this callback
+         * is called, app should launch browser / webview to the given URL.
+         *
+         * @param url URL for browser launch
+         */
+        public void onBrowserLaunch(String url);
+
+        /**
+         * When this is called, app should dismiss the previously lanched browser.
+         */
+        public void onBrowserDismiss();
+    }
+
+    /**
+     * A channel that connects the application to the wifi passpoint framework.
+     * Most passpoint operations require a Channel as an argument.
+     * An instance of Channel is obtained by doing a call on {@link #initialize}
+     */
+    public static class Channel {
+        private final static int INVALID_LISTENER_KEY = 0;
+
+        private ChannelListener mChannelListener;
+
+        private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
+        private HashMap<Integer, Integer> mListenerMapCount = new HashMap<Integer, Integer>();
+        private Object mListenerMapLock = new Object();
+        private int mListenerKey = 0;
+
+        private List<ScanResult> mAnqpRequest = new LinkedList<ScanResult>();
+        private Object mAnqpRequestLock = new Object();
+
+        private AsyncChannel mAsyncChannel;
+        private PasspointHandler mHandler;
+        Context mContext;
+
+        Channel(Context context, Looper looper, ChannelListener l) {
+            mAsyncChannel = new AsyncChannel();
+            mHandler = new PasspointHandler(looper);
+            mChannelListener = l;
+            mContext = context;
+        }
+
+        private int putListener(Object listener) {
+            return putListener(listener, 1);
+        }
+
+        private int putListener(Object listener, int count) {
+            if (listener == null || count <= 0) return INVALID_LISTENER_KEY;
+            int key;
+            synchronized (mListenerMapLock) {
+                do {
+                    key = mListenerKey++;
+                } while (key == INVALID_LISTENER_KEY);
+                mListenerMap.put(key, listener);
+                mListenerMapCount.put(key, count);
+            }
+            return key;
+        }
+
+        private Object getListener(int key, boolean force) {
+            Log.d(TAG, "getListener() key=" + key + " force=" + force);
+            if (key == INVALID_LISTENER_KEY) return null;
+            synchronized (mListenerMapLock) {
+                if (!force) {
+                    int count = mListenerMapCount.get(key);
+                    Log.d(TAG, "count=" + count);
+                    mListenerMapCount.put(key, --count);
+                    if (count > 0) return null;
+                }
+                Log.d(TAG, "remove key");
+                mListenerMapCount.remove(key);
+                return mListenerMap.remove(key);
+            }
+        }
+
+        private void anqpRequestStart(ScanResult sr) {
+            Log.d(TAG, "anqpRequestStart sr.bssid=" + sr.BSSID);
+            synchronized(mAnqpRequestLock) { mAnqpRequest.add(sr); }
+        }
+
+        private void anqpRequestFinish(PasspointInfo result) {
+            Log.d(TAG, "anqpRequestFinish pi.bssid=" + result.bssid);
+            synchronized(mAnqpRequestLock) {
+                for (ScanResult sr : mAnqpRequest)
+                    if (sr.BSSID.equals(result.bssid)) {
+                        Log.d(TAG, "find hit " + result.bssid);
+                        sr.passpoint = result;
+                        mAnqpRequest.remove(sr);
+                        Log.d(TAG, "mAnqpRequest.len=" + mAnqpRequest.size());
+                        break;
+                    }
+            }
+        }
+
+        private void anqpRequestFinish(ScanResult sr) {
+            Log.d(TAG, "anqpRequestFinish sr.bssid=" + sr.BSSID);
+            synchronized(mAnqpRequestLock) {
+                for (ScanResult sr1 : mAnqpRequest)
+                    if (sr1.BSSID.equals(sr.BSSID)) {
+                        mAnqpRequest.remove(sr1);
+                        break;
+                    }
+            }
+        }
+
+        class PasspointHandler extends Handler {
+            PasspointHandler(Looper looper) {
+                super(looper);
+            }
+
+            @Override
+            public void handleMessage(Message message) {
+                Object listener = getListener(message.arg2, false);
+                switch (message.what) {
+                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                        if (mChannelListener != null) {
+                            mChannelListener.onChannelDisconnected();
+                            mChannelListener = null;
+                        }
+                        break;
+
+                    case REQUEST_ANQP_INFO_SUCCEEDED:
+                        PasspointInfo result = (PasspointInfo) message.obj;
+                        anqpRequestFinish(result);
+                        if (listener != null) {
+                            ((ActionListener) listener).onSuccess();
+                        }
+                        break;
+
+                    case REQUEST_ANQP_INFO_FAILED:
+                        anqpRequestFinish((ScanResult) message.obj);
+                        if (listener == null) getListener(message.arg2, true);
+                        if (listener != null) {
+                            ((ActionListener) listener).onFailure(message.arg1);
+                        }
+                        break;
+
+                    default:
+                        Log.d(TAG, "Ignored " + message);
+                        break;
+                }
+            }
+        }
+
+    }
+
+
+    private static final int BASE = Protocol.BASE_WIFI_PASSPOINT_MANAGER;
+
+    /** @hide */
+    public static final int REQUEST_ANQP_INFO                       = BASE + 1;
+
+    /** @hide */
+    public static final int REQUEST_ANQP_INFO_FAILED                = BASE + 2;
+
+    /** @hide */
+    public static final int REQUEST_ANQP_INFO_SUCCEEDED             = BASE + 3;
+
+    /** @hide */
+    public static final int REQUEST_OSU_INFO                        = BASE + 4;
+
+    /** @hide */
+    public static final int REQUEST_OSU_INFO_FAILED                 = BASE + 5;
+
+    /** @hide */
+    public static final int REQUEST_OSU_INFO_SUCCEEDED              = BASE + 6;
+
+
+    private Context mContext;
+    IPasspointManager mService;
+
+
+    /**
+     * TODO: doc
+     * @param context
+     * @param service
+     */
+    public PasspointManager(Context context, IPasspointManager service) {
+        mContext = context;
+        mService = service;
+    }
+
+    /**
+     * Registers the application with the framework. This function must be the
+     * first to be called before any async passpoint operations are performed.
+     *
+     * @param srcContext is the context of the source
+     * @param srcLooper is the Looper on which the callbacks are receivied
+     * @param listener for callback at loss of framework communication. Can be
+     *            null.
+     * @return Channel instance that is necessary for performing any further
+     *         passpoint operations
+     */
+    public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
+        Messenger messenger = getMessenger();
+        if (messenger == null) return null;
+
+        Channel c = new Channel(srcContext, srcLooper, listener);
+        if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
+                == AsyncChannel.STATUS_SUCCESSFUL) {
+            return c;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * STOPSHIP: temp solution, should use supplicant manager instead, check
+     * with b/13931972
+     *
+     * @hide
+     */
+    public Messenger getMessenger() {
+        try {
+            return mService.getMessenger();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Get Passpoint state.
+     *
+     * @return One of {@link #PASSPOINT_STATE_DISABLED},
+     *         {@link #PASSPOINT_STATE_DISCOVERY},
+     *         {@link #PASSPOINT_STATE_ACCESS},
+     *         {@link #PASSPOINT_STATE_PROVISION},
+     *         {@link #PASSPOINT_STATE_UNKNOWN}
+     */
+    public int getPasspointState() {
+        try{
+            return mService.getPasspointState();
+        }
+        catch (RemoteException e) {
+            return PASSPOINT_STATE_UNKNOWN;
+        }
+    }
+
+    /**
+     * TODO: doc
+     *
+     * @param c
+     * @param requested
+     * @param mask
+     * @param listener
+     *
+     * @hide
+     */
+    public void requestAnqpInfo(Channel c, List<ScanResult> requested, int mask,
+            ActionListener listener) {
+        Log.d(TAG, "requestAnqpInfo start");
+        Log.d(TAG, "requested.size=" + requested.size());
+        checkChannel(c);
+        List<ScanResult> list = new ArrayList<ScanResult>();
+        for (ScanResult sr : requested) if (sr.capabilities.contains("[HS20]")) {
+            list.add(sr);
+            c.anqpRequestStart(sr);
+            Log.d(TAG, "adding " + sr.BSSID);
+        }
+        int count = list.size();
+        Log.d(TAG, "after filter, count=" + count);
+        if (count == 0) {
+            if (DBG) Log.d(TAG, "ANQP info request contains no HS20 APs, skipped");
+            listener.onSuccess();
+            return;
+        }
+        int key = c.putListener(listener, count);
+        for (ScanResult sr : list)
+            c.mAsyncChannel.sendMessage(REQUEST_ANQP_INFO, mask, key, sr);
+        Log.d(TAG, "requestAnqpInfo end");
+    }
+
+    /**
+     * TODO: doc
+     *
+     * @param c
+     * @param requested
+     * @param resolution
+     * @param listener
+     */
+    public void requestOsuIcons(Channel c, List<PasspointOsuProvider> requested,
+            int resolution, ActionListener listener) {
+    }
+
+    /**
+     * TODO: doc
+     *
+     * @param requested
+     * @return
+     */
+    public List<PasspointPolicy> requestCredentialMatch(List<ScanResult> requested) {
+        return null;
+    }
+
+    /* TODO: add credential APIs */
+
+    /**
+     * Give a list of all saved Passpoint credentials.
+     *
+     * @return The list of credentials
+     */
+    public List<PasspointCredential> getSavedCredentials() {
+        return null;
+    }
+
+    /**
+     * Add a new Passpoint credential.
+     *
+     * @param cred The credential to be added
+     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     */
+    public boolean addCredential(PasspointCredential cred) {
+        return true;
+    }
+
+    /**
+     * Update an existing Passpoint credential.
+     *
+     * @param cred The credential to be updated
+     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     */
+    public boolean updateCredential(PasspointCredential cred) {
+        return true;
+    }
+
+    /**
+     * Remove an existing Passpoint credential.
+     *
+     * @param cred The credential to be removed
+     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     */
+    public boolean removeCredential(PasspointCredential cred) {
+        return true;
+    }
+
+    /** @hide */
+    public void startOsu(Channel c, PasspointOsuProvider selected, OsuRemListener listener) {
+
+    }
+
+    /** @hide */
+    public void startUserRemediation(Channel c, OsuRemListener listener) {
+    }
+
+    /**
+     * Select and connect to a Passpoint network.
+     *
+     * @param selected Selected Passpoint network, see {@link PasspointPolicy}
+     */
+    public void connect(PasspointPolicy selected) {
+    }
+
+    private static void checkChannel(Channel c) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    }
+}
diff --git a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl b/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
similarity index 77%
copy from wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
copy to wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
index 2b1601b..f5ecb7c 100644
--- a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
@@ -14,15 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.hotspot;
+package android.net.wifi.passpoint;
 
-/**
- * Interface that allows controlling and querying Hotspot connectivity.
- *
- * {@hide}
- */
-interface IWifiHotspotManager
-{
-    void test();
-}
-
+parcelable PasspointOsuProvider;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java b/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java
new file mode 100644
index 0000000..80d5315
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java
@@ -0,0 +1,145 @@
+/*
+ * 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.net.wifi.passpoint;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * TODO: doc
+ */
+public class PasspointOsuProvider implements Parcelable {
+
+    /** TODO: doc */
+    public static final int OSU_METHOD_UNKNOWN = -1;
+
+    /** TODO: doc */
+    public static final int OSU_METHOD_OMADM = 0;
+
+    /** TODO: doc */
+    public static final int OSU_METHOD_SOAP = 1;
+
+    /** TODO: doc */
+    public String ssid;
+
+    /** TODO: doc */
+    public String friendlyName;
+
+    /** TODO: doc */
+    public String serverUri;
+
+    /** TODO: doc */
+    public int osuMethod = OSU_METHOD_UNKNOWN;
+
+    /** TODO: doc */
+    public int iconWidth;
+
+    /** TODO: doc */
+    public int iconHeight;
+
+    /** TODO: doc */
+    public String iconType;
+
+    /** TODO: doc */
+    public String iconFileName;
+
+    /** TODO: doc */
+    public Object icon; // TODO: should change to image format
+
+    /** TODO: doc */
+    public String osuNai;
+
+    /** TODO: doc */
+    public String osuService;
+
+
+    /** default constructor @hide */
+    public PasspointOsuProvider() {
+        // TODO
+    }
+
+    /** copy constructor @hide */
+    public PasspointOsuProvider(PasspointOsuProvider source) {
+        // TODO
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("SSID: ").append(ssid);
+        if (friendlyName != null)
+            sb.append(" friendlyName: ").append(friendlyName);
+        if (serverUri != null)
+            sb.append(" serverUri: ").append(serverUri);
+        sb.append(" osuMethod: ").append(osuMethod);
+        if (iconFileName != null) {
+            sb.append(" icon: [").append(iconWidth).append("x")
+              .append(iconHeight).append(" ")
+              .append(iconType).append(" ")
+              .append(iconFileName);
+        }
+        if (osuNai != null)
+            sb.append(" osuNai: ").append(osuNai);
+        if (osuService != null)
+            sb.append(" osuService: ").append(osuService);
+        return sb.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeValue(ssid);
+        out.writeValue(friendlyName);
+        out.writeValue(serverUri);
+        out.writeInt(osuMethod);
+        out.writeInt(iconWidth);
+        out.writeInt(iconHeight);
+        out.writeValue(iconType);
+        out.writeValue(iconFileName);
+        out.writeValue(osuNai);
+        out.writeValue(osuService);
+        // TODO: icon image?
+    }
+
+    public static final Parcelable.Creator<PasspointOsuProvider> CREATOR =
+            new Parcelable.Creator<PasspointOsuProvider>() {
+        @Override
+        public PasspointOsuProvider createFromParcel(Parcel in) {
+            PasspointOsuProvider osu = new PasspointOsuProvider();
+            osu.ssid = (String) in.readValue(String.class.getClassLoader());
+            osu.friendlyName = (String) in.readValue(String.class.getClassLoader());
+            osu.serverUri = (String) in.readValue(String.class.getClassLoader());
+            osu.osuMethod = in.readInt();
+            osu.iconWidth = in.readInt();
+            osu.iconHeight = in.readInt();
+            osu.iconType = (String) in.readValue(String.class.getClassLoader());
+            osu.iconFileName = (String) in.readValue(String.class.getClassLoader());
+            osu.osuNai = (String) in.readValue(String.class.getClassLoader());
+            osu.osuService = (String) in.readValue(String.class.getClassLoader());
+            return osu;
+        }
+
+        @Override
+        public PasspointOsuProvider[] newArray(int size) {
+            return new PasspointOsuProvider[size];
+        }
+    };
+}
diff --git a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl b/wifi/java/android/net/wifi/passpoint/PasspointPolicy.aidl
similarity index 77%
copy from wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
copy to wifi/java/android/net/wifi/passpoint/PasspointPolicy.aidl
index 2b1601b..c2cc731 100644
--- a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/PasspointPolicy.aidl
@@ -14,15 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.hotspot;
+package android.net.wifi.passpoint;
 
-/**
- * Interface that allows controlling and querying Hotspot connectivity.
- *
- * {@hide}
- */
-interface IWifiHotspotManager
-{
-    void test();
-}
-
+parcelable PasspointPolicy;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java b/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java
new file mode 100644
index 0000000..3a8806b
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java
@@ -0,0 +1,55 @@
+/*

+ * 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.net.wifi.passpoint;

+

+import android.os.Parcelable;

+import android.os.Parcel;

+

+public class PasspointPolicy implements Parcelable {

+

+    @Override

+    public String toString() {

+        // TODO

+        return null;

+    }

+

+    /** Implement the Parcelable interface {@hide} */

+    @Override

+    public int describeContents() {

+        return 0;

+    }

+

+    /** Implement the Parcelable interface {@hide} */

+    @Override

+    public void writeToParcel(Parcel dest, int flags) {

+        // TODO

+    }

+

+    /** Implement the Parcelable interface {@hide} */

+    public static final Creator<PasspointPolicy> CREATOR =

+            new Creator<PasspointPolicy>() {

+                @Override

+                public PasspointPolicy createFromParcel(Parcel in) {

+                    return null;

+                }

+

+                @Override

+                public PasspointPolicy[] newArray(int size) {

+                    return new PasspointPolicy[size];

+                }

+            };

+}

diff --git a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl b/wifi/java/android/net/wifi/passpoint/WifiTree.aidl
similarity index 77%
copy from wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
copy to wifi/java/android/net/wifi/passpoint/WifiTree.aidl
index 2b1601b..8e2fab742 100644
--- a/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiTree.aidl
@@ -14,15 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.hotspot;
+package android.net.wifi.passpoint;
 
-/**
- * Interface that allows controlling and querying Hotspot connectivity.
- *
- * {@hide}
- */
-interface IWifiHotspotManager
-{
-    void test();
-}
-
+parcelable WifiTree;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiTree.java b/wifi/java/android/net/wifi/passpoint/WifiTree.java
new file mode 100644
index 0000000..8fdb6e1
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiTree.java
@@ -0,0 +1,51 @@
+/*

+ * 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.net.wifi.passpoint;

+

+import android.os.Parcelable;

+import android.os.Parcel;

+

+/** @hide */

+public class WifiTree implements Parcelable {

+

+    /** Implement the Parcelable interface {@hide} */

+    @Override

+    public int describeContents() {

+        return 0;

+    }

+

+    /** Implement the Parcelable interface {@hide} */

+    @Override

+    public void writeToParcel(Parcel out, int flags) {

+        // TODO

+    }

+

+    /** Implement the Parcelable interface {@hide} */

+    public static final Parcelable.Creator<WifiTree> CREATOR =

+            new Parcelable.Creator<WifiTree>() {

+                @Override

+                public WifiTree createFromParcel(Parcel in) {

+                    // TODO

+                    return null;

+                }

+

+                @Override

+                public WifiTree[] newArray(int size) {

+                    return new WifiTree[size];

+                }

+            };

+}