Merge "add ranking information to the dumpsys info"
diff --git a/Android.mk b/Android.mk
index 9828ea6..58509a7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -171,7 +171,6 @@
 	core/java/android/nfc/INfcAdapterExtras.aidl \
 	core/java/android/nfc/INfcTag.aidl \
 	core/java/android/nfc/INfcCardEmulation.aidl \
-	core/java/android/nfc/INfcUnlockSettings.aidl \
 	core/java/android/os/IBatteryPropertiesListener.aidl \
 	core/java/android/os/IBatteryPropertiesRegistrar.aidl \
 	core/java/android/os/ICancellationSignal.aidl \
@@ -334,7 +333,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/passpoint/IPasspointManager.aidl \
+	wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.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 8f2a815..def0755 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4424,6 +4424,8 @@
     ctor public Notification(android.os.Parcel);
     method public android.app.Notification clone();
     method public int describeContents();
+    method public java.lang.String getGroup();
+    method public java.lang.String getSortKey();
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -4466,6 +4468,7 @@
     field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
     field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
     field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
+    field public static final int FLAG_GROUP_SUMMARY = 512; // 0x200
     field public static final deprecated int FLAG_HIGH_PRIORITY = 128; // 0x80
     field public static final int FLAG_INSISTENT = 4; // 0x4
     field public static final int FLAG_LOCAL_ONLY = 256; // 0x100
@@ -4516,6 +4519,7 @@
     method public android.app.Notification.Action clone();
     method public int describeContents();
     method public android.os.Bundle getExtras();
+    method public android.app.RemoteInput[] getRemoteInputs();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public android.app.PendingIntent actionIntent;
@@ -4523,14 +4527,20 @@
     field public java.lang.CharSequence title;
   }
 
-  public static class Notification.Action.Builder {
+  public static final class Notification.Action.Builder {
     ctor public Notification.Action.Builder(int, java.lang.CharSequence, android.app.PendingIntent);
     ctor public Notification.Action.Builder(android.app.Notification.Action);
     method public android.app.Notification.Action.Builder addExtras(android.os.Bundle);
+    method public android.app.Notification.Action.Builder addRemoteInput(android.app.RemoteInput);
+    method public android.app.Notification.Action.Builder apply(android.app.Notification.Action.Builder.Extender);
     method public android.app.Notification.Action build();
     method public android.os.Bundle getExtras();
   }
 
+  public static abstract interface Notification.Action.Builder.Extender {
+    method public abstract android.app.Notification.Action.Builder applyTo(android.app.Notification.Action.Builder);
+  }
+
   public static class Notification.BigPictureStyle extends android.app.Notification.Style {
     ctor public Notification.BigPictureStyle();
     ctor public Notification.BigPictureStyle(android.app.Notification.Builder);
@@ -4554,6 +4564,7 @@
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
+    method public android.app.Notification.Builder apply(android.app.Notification.Builder.Extender);
     method public android.app.Notification build();
     method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
@@ -4569,6 +4580,8 @@
     method public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setExtras(android.os.Bundle);
     method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean);
+    method public android.app.Notification.Builder setGroup(java.lang.String);
+    method public android.app.Notification.Builder setGroupSummary(boolean);
     method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap);
     method public android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
@@ -4581,6 +4594,7 @@
     method public android.app.Notification.Builder setShowWhen(boolean);
     method public android.app.Notification.Builder setSmallIcon(int);
     method public android.app.Notification.Builder setSmallIcon(int, int);
+    method public android.app.Notification.Builder setSortKey(java.lang.String);
     method public android.app.Notification.Builder setSound(android.net.Uri);
     method public android.app.Notification.Builder setSound(android.net.Uri, int);
     method public android.app.Notification.Builder setStyle(android.app.Notification.Style);
@@ -4593,6 +4607,10 @@
     method public android.app.Notification.Builder setWhen(long);
   }
 
+  public static abstract interface Notification.Builder.Extender {
+    method public abstract android.app.Notification.Builder applyTo(android.app.Notification.Builder);
+  }
+
   public static class Notification.InboxStyle extends android.app.Notification.Style {
     ctor public Notification.InboxStyle();
     ctor public Notification.InboxStyle(android.app.Notification.Builder);
@@ -4696,6 +4714,31 @@
     field public static final int STYLE_SPINNER = 0; // 0x0
   }
 
+  public final class RemoteInput implements android.os.Parcelable {
+    method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
+    method public int describeContents();
+    method public boolean getAllowFreeFormInput();
+    method public java.lang.CharSequence[] getChoices();
+    method public android.os.Bundle getExtras();
+    method public java.lang.CharSequence getLabel();
+    method public java.lang.String getResultKey();
+    method public static android.os.Bundle getResultsFromIntent(android.content.Intent);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final java.lang.String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+    field public static final java.lang.String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+  }
+
+  public static final class RemoteInput.Builder {
+    ctor public RemoteInput.Builder(java.lang.String);
+    method public android.app.RemoteInput.Builder addExtras(android.os.Bundle);
+    method public android.app.RemoteInput build();
+    method public android.os.Bundle getExtras();
+    method public android.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
+    method public android.app.RemoteInput.Builder setChoices(java.lang.CharSequence[]);
+    method public android.app.RemoteInput.Builder setLabel(java.lang.CharSequence);
+  }
+
   public class SearchManager implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
     method public android.content.ComponentName getGlobalSearchActivity();
     method public android.app.SearchableInfo getSearchableInfo(android.content.ComponentName);
@@ -5053,6 +5096,7 @@
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean isActivePasswordSufficient();
     method public boolean isAdminActive(android.content.ComponentName);
+    method public boolean isApplicationBlocked(android.content.ComponentName, java.lang.String);
     method public boolean isDeviceOwnerApp(java.lang.String);
     method public boolean isLockTaskPermitted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
@@ -5060,8 +5104,11 @@
     method public void removeActiveAdmin(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
+    method public boolean setApplicationBlocked(android.content.ComponentName, java.lang.String, boolean);
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
+    method public int setApplicationsBlocked(android.content.ComponentName, android.content.Intent, boolean);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
+    method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
     method public void setLockTaskComponents(android.content.ComponentName[]) throws java.lang.SecurityException;
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -5077,6 +5124,7 @@
     method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
     method public void setPasswordQuality(android.content.ComponentName, int);
     method public void setProfileEnabled(android.content.ComponentName);
+    method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void wipeData(int);
     field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
@@ -5230,6 +5278,80 @@
 
 }
 
+package android.app.wearable {
+
+  public final class WearableActionExtensions implements android.app.Notification.Action.Builder.Extender android.os.Parcelable {
+    method public android.app.Notification.Action.Builder applyTo(android.app.Notification.Action.Builder);
+    method public int describeContents();
+    method public static android.app.wearable.WearableActionExtensions from(android.app.Notification.Action);
+    method public boolean isAvailableOffline();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static final class WearableActionExtensions.Builder {
+    ctor public WearableActionExtensions.Builder();
+    ctor public WearableActionExtensions.Builder(android.app.wearable.WearableActionExtensions);
+    method public android.app.wearable.WearableActionExtensions build();
+    method public android.app.wearable.WearableActionExtensions.Builder setAvailableOffline(boolean);
+  }
+
+  public final class WearableNotificationExtensions implements android.app.Notification.Builder.Extender android.os.Parcelable {
+    method public android.app.Notification.Builder applyTo(android.app.Notification.Builder);
+    method public int describeContents();
+    method public static android.app.wearable.WearableNotificationExtensions from(android.app.Notification);
+    method public android.app.Notification.Action getAction(int);
+    method public int getActionCount();
+    method public android.app.Notification.Action[] getActions();
+    method public android.graphics.Bitmap getBackground();
+    method public int getContentAction();
+    method public int getContentIcon();
+    method public int getContentIconGravity();
+    method public boolean getContentIntentAvailableOffline();
+    method public int getCustomContentHeight();
+    method public int getCustomSizePreset();
+    method public android.app.PendingIntent getDisplayIntent();
+    method public int getGravity();
+    method public boolean getHintHideIcon();
+    method public boolean getHintShowBackgroundOnly();
+    method public android.app.Notification[] getPages();
+    method public boolean getStartScrollBottom();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int SIZE_DEFAULT = 0; // 0x0
+    field public static final int SIZE_LARGE = 4; // 0x4
+    field public static final int SIZE_MEDIUM = 3; // 0x3
+    field public static final int SIZE_SMALL = 2; // 0x2
+    field public static final int SIZE_XSMALL = 1; // 0x1
+    field public static final int UNSET_ACTION_INDEX = -1; // 0xffffffff
+  }
+
+  public static final class WearableNotificationExtensions.Builder {
+    ctor public WearableNotificationExtensions.Builder();
+    ctor public WearableNotificationExtensions.Builder(android.app.wearable.WearableNotificationExtensions);
+    method public android.app.wearable.WearableNotificationExtensions.Builder addAction(android.app.Notification.Action);
+    method public android.app.wearable.WearableNotificationExtensions.Builder addActions(java.util.List<android.app.Notification.Action>);
+    method public android.app.wearable.WearableNotificationExtensions.Builder addPage(android.app.Notification);
+    method public android.app.wearable.WearableNotificationExtensions.Builder addPages(java.util.List<android.app.Notification>);
+    method public android.app.wearable.WearableNotificationExtensions build();
+    method public android.app.wearable.WearableNotificationExtensions.Builder clearActions();
+    method public android.app.wearable.WearableNotificationExtensions.Builder clearPages();
+    method public android.app.wearable.WearableNotificationExtensions.Builder setBackground(android.graphics.Bitmap);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setContentAction(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setContentIcon(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setContentIconGravity(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setContentIntentAvailableOffline(boolean);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setCustomContentHeight(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setCustomSizePreset(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setDisplayIntent(android.app.PendingIntent);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setGravity(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setHintHideIcon(boolean);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setHintShowBackgroundOnly(boolean);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setStartScrollBottom(boolean);
+  }
+
+}
+
 package android.appwidget {
 
   public class AppWidgetHost {
@@ -6018,6 +6140,7 @@
     ctor public BluetoothLeAdvertiseScanData();
     field public static final int ADVERTISING_DATA = 0; // 0x0
     field public static final int PARSED_SCAN_RECORD = 2; // 0x2
+    field public static final int SCAN_RESPONSE_DATA = 1; // 0x1
   }
 
   public static abstract class BluetoothLeAdvertiseScanData.AdvertiseBaseData {
@@ -6061,6 +6184,7 @@
 
   public class BluetoothLeAdvertiser {
     method public void startAdvertising(android.bluetooth.BluetoothLeAdvertiser.Settings, android.bluetooth.BluetoothLeAdvertiseScanData.AdvertisementData, android.bluetooth.BluetoothLeAdvertiser.AdvertiseCallback);
+    method public void startAdvertising(android.bluetooth.BluetoothLeAdvertiser.Settings, android.bluetooth.BluetoothLeAdvertiseScanData.AdvertisementData, android.bluetooth.BluetoothLeAdvertiseScanData.AdvertisementData, android.bluetooth.BluetoothLeAdvertiser.AdvertiseCallback);
     method public void stopAdvertising(android.bluetooth.BluetoothLeAdvertiser.Settings, android.bluetooth.BluetoothLeAdvertiser.AdvertiseCallback);
   }
 
@@ -8271,6 +8395,7 @@
     field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
     field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
     field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
+    field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
     field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
     field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
     field public static final int GET_ACTIVITIES = 1; // 0x1
@@ -10376,10 +10501,10 @@
     ctor public Outline();
     ctor public Outline(android.graphics.Outline);
     method public boolean canClip();
-    method public boolean isValid();
-    method public void reset();
+    method public boolean isEmpty();
     method public void set(android.graphics.Outline);
     method public void setConvexPath(android.graphics.Path);
+    method public void setEmpty();
     method public void setOval(int, int, int, int);
     method public void setOval(android.graphics.Rect);
     method public void setRect(int, int, int, int);
@@ -12827,15 +12952,14 @@
 
   public class UsbConfiguration implements android.os.Parcelable {
     method public int describeContents();
-    method public int getAttributes();
     method public int getId();
     method public android.hardware.usb.UsbInterface getInterface(int);
     method public int getInterfaceCount();
     method public int getMaxPower();
     method public java.lang.String getName();
+    method public boolean isRemoteWakeup();
+    method public boolean isSelfPowered();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final int ATTR_REMOTE_WAKEUP_MASK = 32; // 0x20
-    field public static final int ATTR_SELF_POWERED_MASK = 64; // 0x40
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
@@ -14936,6 +15060,7 @@
     ctor public RemoteControlClient(android.app.PendingIntent);
     ctor public RemoteControlClient(android.app.PendingIntent, android.os.Looper);
     method public android.media.RemoteControlClient.MetadataEditor editMetadata(boolean);
+    method public android.media.session.MediaSession getMediaSession();
     method public void setMetadataUpdateListener(android.media.RemoteControlClient.OnMetadataUpdateListener);
     method public void setOnGetPlaybackPositionListener(android.media.RemoteControlClient.OnGetPlaybackPositionListener);
     method public void setPlaybackPositionUpdateListener(android.media.RemoteControlClient.OnPlaybackPositionUpdateListener);
@@ -16904,9 +17029,11 @@
   }
 
   public static final class WifiEnterpriseConfig.Eap {
+    field public static final int AKA = 5; // 0x5
     field public static final int NONE = -1; // 0xffffffff
     field public static final int PEAP = 0; // 0x0
     field public static final int PWD = 3; // 0x3
+    field public static final int SIM = 4; // 0x4
     field public static final int TLS = 1; // 0x1
     field public static final int TTLS = 2; // 0x2
   }
@@ -16940,6 +17067,7 @@
   public class WifiManager {
     method public int addNetwork(android.net.wifi.WifiConfiguration);
     method public static int calculateSignalLevel(int, int);
+    method public void cancelWps(android.net.wifi.WifiManager.ActionListener);
     method public static int compareSignalLevel(int, int);
     method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String);
     method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String);
@@ -16963,9 +17091,12 @@
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
     method public boolean setWifiEnabled(boolean);
     method public boolean startScan();
+    method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsListener);
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
+    field public static final int BUSY = 2; // 0x2
+    field public static final int ERROR = 0; // 0x0
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
     field public static final java.lang.String EXTRA_BSSID = "bssid";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
@@ -16976,6 +17107,8 @@
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
     field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
+    field public static final int INVALID_ARGS = 8; // 0x8
+    field public static final int IN_PROGRESS = 1; // 0x1
     field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
     field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
     field public static final java.lang.String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
@@ -16991,6 +17124,16 @@
     field public static final int WIFI_STATE_ENABLED = 3; // 0x3
     field public static final int WIFI_STATE_ENABLING = 2; // 0x2
     field public static final int WIFI_STATE_UNKNOWN = 4; // 0x4
+    field public static final int WPS_AUTH_FAILURE = 6; // 0x6
+    field public static final int WPS_OVERLAP_ERROR = 3; // 0x3
+    field public static final int WPS_TIMED_OUT = 7; // 0x7
+    field public static final int WPS_TKIP_ONLY_PROHIBITED = 5; // 0x5
+    field public static final int WPS_WEP_PROHIBITED = 4; // 0x4
+  }
+
+  public static abstract interface WifiManager.ActionListener {
+    method public abstract void onFailure(int);
+    method public abstract void onSuccess();
   }
 
   public class WifiManager.MulticastLock {
@@ -17008,6 +17151,12 @@
     method public void setWorkSource(android.os.WorkSource);
   }
 
+  public static abstract interface WifiManager.WpsListener {
+    method public abstract void onCompletion();
+    method public abstract void onFailure(int);
+    method public abstract void onStartSuccess(java.lang.String);
+  }
+
   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);
@@ -17093,6 +17242,7 @@
     ctor public WpsInfo(android.net.wifi.WpsInfo);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
+    field public java.lang.String BSSID;
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int DISPLAY = 1; // 0x1
     field public static final int INVALID = 4; // 0x4
@@ -17302,108 +17452,23 @@
 
 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();
+  public class WifiPasspointCredential implements android.os.Parcelable {
+    ctor public WifiPasspointCredential(java.lang.String, android.net.wifi.WifiEnterpriseConfig);
     method public int describeContents();
+    method public java.lang.String getClientCertPath();
+    method public int getEapMethod();
+    method public java.lang.String getFqdn();
+    method public java.lang.String getImsi();
+    method public java.lang.String getRealm();
+    method public java.lang.String getUserName();
     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);
+  public class WifiPasspointManager {
+    method public boolean addCredential(android.net.wifi.passpoint.WifiPasspointCredential);
+    method public java.util.List<android.net.wifi.passpoint.WifiPasspointCredential> getSavedCredentials();
+    method public boolean removeCredential(android.net.wifi.passpoint.WifiPasspointCredential);
+    method public boolean updateCredential(android.net.wifi.passpoint.WifiPasspointCredential);
   }
 
 }
@@ -17525,11 +17590,6 @@
     method public android.nfc.NfcAdapter getDefaultAdapter();
   }
 
-  public class NfcUnlock {
-    method public static synchronized android.nfc.NfcUnlock getInstance(android.nfc.NfcAdapter);
-    method public boolean getNfcUnlockEnabled();
-  }
-
   public final class Tag implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getId();
@@ -20993,6 +21053,7 @@
     field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
     field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
     field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
+    field public static final java.lang.String DISALLOW_TELEPHONY = "no_telephony";
     field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
     field public static final java.lang.String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
     field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
@@ -23889,7 +23950,6 @@
     field public static final java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
     field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
     field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference";
-    field public static final java.lang.String NFC_UNLOCK_ENABLED = "nfc_unlock_enabled";
     field public static final java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
     field public static final java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
     field public static final java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
@@ -25036,8 +25096,8 @@
     method public void setErrorHandler(android.renderscript.RenderScript.RSErrorHandler);
     method public void setMessageHandler(android.renderscript.RenderScript.RSMessageHandler);
     method public void setPriority(android.renderscript.RenderScript.Priority);
-    field public static final long CREATE_FLAG_LOW_LATENCY = 1L; // 0x1L
-    field public static final long CREATE_FLAG_LOW_POWER = 2L; // 0x2L
+    field public static final long CREATE_FLAG_LOW_LATENCY = 2L; // 0x2L
+    field public static final long CREATE_FLAG_LOW_POWER = 4L; // 0x4L
     field public static final long CREATE_FLAG_NONE = 0L; // 0x0L
   }
 
@@ -25557,10 +25617,10 @@
   public class FingerprintManager {
     ctor public FingerprintManager(android.content.Context);
     method public void enroll(long);
+    method public boolean enrolledAndEnabled();
     method public void remove(int);
     method public void startListening(android.service.fingerprint.FingerprintManagerReceiver);
     method public void stopListening();
-    field protected static final boolean DEBUG = true;
     field public static final int FINGERPRINT_ERROR = -1; // 0xffffffff
     field public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2; // 0x2
     field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6324d4c..9053af2 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.passpoint.IPasspointManager;
-import android.net.wifi.passpoint.PasspointManager;
+import android.net.wifi.passpoint.IWifiPasspointManager;
+import android.net.wifi.passpoint.WifiPasspointManager;
 import android.net.wifi.p2p.IWifiP2pManager;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcManager;
@@ -581,8 +581,8 @@
         registerService(WIFI_PASSPOINT_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(WIFI_PASSPOINT_SERVICE);
-                    IPasspointManager service = IPasspointManager.Stub.asInterface(b);
-                    return new PasspointManager(ctx.getOuterContext(), service);
+                    IWifiPasspointManager service = IWifiPasspointManager.Stub.asInterface(b);
+                    return new WifiPasspointManager(ctx.getOuterContext(), service);
                 }});
 
         registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
@@ -1377,7 +1377,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, receiverPermission,
-                    AppOpsManager.OP_NONE, true, false, user.getIdentifier());
+                    appOp, true, false, user.getIdentifier());
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fd76b9c4..59b3a27 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -45,6 +45,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.text.NumberFormat;
 import java.util.ArrayList;
+import java.util.Collections;
 
 /**
  * A class that represents how a persistent notification is to be presented to
@@ -370,6 +371,14 @@
      */
     public static final int FLAG_LOCAL_ONLY         = 0x00000100;
 
+    /**
+     * Bit to be bitswise-ored into the {@link #flags} field that should be
+     * set if this notification is the group summary for a group of notifications.
+     * Grouped notifications may display in a cluster or stack on devices which
+     * support such rendering. Requires a group key also be set using {@link Builder#setGroup}.
+     */
+    public static final int FLAG_GROUP_SUMMARY      = 0x00000200;
+
     public int flags;
 
     /** @hide */
@@ -539,6 +548,34 @@
      */
     public String category;
 
+    private String mGroupKey;
+
+    /**
+     * Get the key used to group this notification into a cluster or stack
+     * with other notifications on devices which support such rendering.
+     */
+    public String getGroup() {
+        return mGroupKey;
+    }
+
+    private String mSortKey;
+
+    /**
+     * Get a sort key that orders this notification among other notifications from the
+     * same package. This can be useful if an external sort was already applied and an app
+     * would like to preserve this. Notifications will be sorted lexicographically using this
+     * value, although providing different priorities in addition to providing sort key may
+     * cause this value to be ignored.
+     *
+     * <p>This sort key can also be used to order members of a notification group. See
+     * {@link Builder#setGroup}.
+     *
+     * @see String#compareTo(String)
+     */
+    public String getSortKey() {
+        return mSortKey;
+    }
+
     /**
      * Additional semantic data to be carried around with this Notification.
      * <p>
@@ -706,15 +743,18 @@
      */
     public static class Action implements Parcelable {
         private final Bundle mExtras;
+        private RemoteInput[] mRemoteInputs;
 
         /**
          * Small icon representing the action.
          */
         public int icon;
+
         /**
          * Title of the action.
          */
         public CharSequence title;
+
         /**
          * Intent to send when the user invokes this action. May be null, in which case the action
          * may be rendered in a disabled presentation by the system UI.
@@ -728,19 +768,23 @@
                 actionIntent = PendingIntent.CREATOR.createFromParcel(in);
             }
             mExtras = in.readBundle();
+            mRemoteInputs = in.createTypedArray(RemoteInput.CREATOR);
         }
+
         /**
          * Use {@link Notification.Builder#addAction(int, CharSequence, PendingIntent)}.
          */
         public Action(int icon, CharSequence title, PendingIntent intent) {
-            this(icon, title, intent, new Bundle());
+            this(icon, title, intent, new Bundle(), null);
         }
 
-        private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
+        private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras,
+                RemoteInput[] remoteInputs) {
             this.icon = icon;
             this.title = title;
             this.actionIntent = intent;
             this.mExtras = extras != null ? extras : new Bundle();
+            this.mRemoteInputs = remoteInputs;
         }
 
         /**
@@ -751,13 +795,22 @@
         }
 
         /**
+         * Get the list of inputs to be collected from the user when this action is sent.
+         * May return null if no remote inputs were added.
+         */
+        public RemoteInput[] getRemoteInputs() {
+            return mRemoteInputs;
+        }
+
+        /**
          * Builder class for {@link Action} objects.
          */
-        public static class Builder {
+        public static final class Builder {
             private final int mIcon;
             private final CharSequence mTitle;
             private final PendingIntent mIntent;
             private final Bundle mExtras;
+            private ArrayList<RemoteInput> mRemoteInputs;
 
             /**
              * Construct a new builder for {@link Action} object.
@@ -766,7 +819,7 @@
              * @param intent the {@link PendingIntent} to fire when users trigger this action
              */
             public Builder(int icon, CharSequence title, PendingIntent intent) {
-                this(icon, title, intent, new Bundle());
+                this(icon, title, intent, new Bundle(), null);
             }
 
             /**
@@ -775,14 +828,20 @@
              * @param action the action to read fields from.
              */
             public Builder(Action action) {
-                this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras));
+                this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras),
+                        action.getRemoteInputs());
             }
 
-            private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
+            private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras,
+                    RemoteInput[] remoteInputs) {
                 mIcon = icon;
                 mTitle = title;
                 mIntent = intent;
                 mExtras = extras;
+                if (remoteInputs != null) {
+                    mRemoteInputs = new ArrayList<RemoteInput>(remoteInputs.length);
+                    Collections.addAll(mRemoteInputs, remoteInputs);
+                }
             }
 
             /**
@@ -809,22 +868,62 @@
             }
 
             /**
+             * Add an input to be collected from the user when this action is sent.
+             * Response values can be retrieved from the fired intent by using the
+             * {@link RemoteInput#getResultsFromIntent} function.
+             * @param remoteInput a {@link RemoteInput} to add to the action
+             * @return this object for method chaining
+             */
+            public Builder addRemoteInput(RemoteInput remoteInput) {
+                if (mRemoteInputs == null) {
+                    mRemoteInputs = new ArrayList<RemoteInput>();
+                }
+                mRemoteInputs.add(remoteInput);
+                return this;
+            }
+
+            /**
+             * Apply an extender to this action builder. Extenders may be used to add
+             * metadata or change options on this builder.
+             */
+            public Builder apply(Extender extender) {
+                extender.applyTo(this);
+                return this;
+            }
+
+            /**
+             * Extender interface for use with {@link #apply}. Extenders may be used to add
+             * metadata or change options on this builder.
+             */
+            public interface Extender {
+                /**
+                 * Apply this extender to a notification action builder.
+                 * @param builder the builder to be modified.
+                 * @return the build object for chaining.
+                 */
+                public Builder applyTo(Builder builder);
+            }
+
+            /**
              * Combine all of the options that have been set and return a new {@link Action}
              * object.
              * @return the built action
              */
             public Action build() {
-                return new Action(mIcon, mTitle, mIntent, mExtras);
+                RemoteInput[] remoteInputs = mRemoteInputs != null
+                        ? mRemoteInputs.toArray(new RemoteInput[mRemoteInputs.size()]) : null;
+                return new Action(mIcon, mTitle, mIntent, mExtras, remoteInputs);
             }
         }
 
         @Override
         public Action clone() {
             return new Action(
-                this.icon,
-                this.title,
-                this.actionIntent, // safe to alias
-                new Bundle(this.mExtras));
+                    icon,
+                    title,
+                    actionIntent, // safe to alias
+                    new Bundle(mExtras),
+                    getRemoteInputs());
         }
         @Override
         public int describeContents() {
@@ -841,6 +940,7 @@
                 out.writeInt(0);
             }
             out.writeBundle(mExtras);
+            out.writeTypedArray(mRemoteInputs, flags);
         }
         public static final Parcelable.Creator<Action> CREATOR =
                 new Parcelable.Creator<Action>() {
@@ -960,6 +1060,10 @@
 
         category = parcel.readString();
 
+        mGroupKey = parcel.readString();
+
+        mSortKey = parcel.readString();
+
         extras = parcel.readBundle(); // may be null
 
         actions = parcel.createTypedArray(Action.CREATOR); // may be null
@@ -1037,6 +1141,10 @@
 
         that.category = this.category;
 
+        that.mGroupKey = this.mGroupKey;
+
+        that.mSortKey = this.mSortKey;
+
         if (this.extras != null) {
             try {
                 that.extras = new Bundle(this.extras);
@@ -1188,6 +1296,10 @@
 
         parcel.writeString(category);
 
+        parcel.writeString(mGroupKey);
+
+        parcel.writeString(mSortKey);
+
         parcel.writeBundle(extras); // null ok
 
         parcel.writeTypedArray(actions, 0); // null ok
@@ -1325,7 +1437,18 @@
         sb.append(" flags=0x");
         sb.append(Integer.toHexString(this.flags));
         sb.append(String.format(" color=0x%08x", this.color));
-        sb.append(" category="); sb.append(this.category);
+        if (this.category != null) {
+            sb.append(" category=");
+            sb.append(this.category);
+        }
+        if (this.mGroupKey != null) {
+            sb.append(" groupKey=");
+            sb.append(this.mGroupKey);
+        }
+        if (this.mSortKey != null) {
+            sb.append(" sortKey=");
+            sb.append(this.mSortKey);
+        }
         if (actions != null) {
             sb.append(" ");
             sb.append(actions.length);
@@ -1408,6 +1531,8 @@
         private int mProgress;
         private boolean mProgressIndeterminate;
         private String mCategory;
+        private String mGroupKey;
+        private String mSortKey;
         private Bundle mExtras;
         private int mPriority;
         private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
@@ -1839,6 +1964,51 @@
         }
 
         /**
+         * Set this notification to be part of a group of notifications sharing the same key.
+         * Grouped notifications may display in a cluster or stack on devices which
+         * support such rendering.
+         *
+         * <p>To make this notification the summary for its group, also call
+         * {@link #setGroupSummary}. A sort order can be specified for group members by using
+         * {@link #setSortKey}.
+         * @param groupKey The group key of the group.
+         * @return this object for method chaining
+         */
+        public Builder setGroup(String groupKey) {
+            mGroupKey = groupKey;
+            return this;
+        }
+
+        /**
+         * Set this notification to be the group summary for a group of notifications.
+         * Grouped notifications may display in a cluster or stack on devices which
+         * support such rendering. Requires a group key also be set using {@link #setGroup}.
+         * @param isGroupSummary Whether this notification should be a group summary.
+         * @return this object for method chaining
+         */
+        public Builder setGroupSummary(boolean isGroupSummary) {
+            setFlag(FLAG_GROUP_SUMMARY, isGroupSummary);
+            return this;
+        }
+
+        /**
+         * Set a sort key that orders this notification among other notifications from the
+         * same package. This can be useful if an external sort was already applied and an app
+         * would like to preserve this. Notifications will be sorted lexicographically using this
+         * value, although providing different priorities in addition to providing sort key may
+         * cause this value to be ignored.
+         *
+         * <p>This sort key can also be used to order members of a notification group. See
+         * {@link #setGroup}.
+         *
+         * @see String#compareTo(String)
+         */
+        public Builder setSortKey(String sortKey) {
+            mSortKey = sortKey;
+            return this;
+        }
+
+        /**
          * Merge additional metadata into this notification.
          *
          * <p>Values within the Bundle will replace existing extras values in this Builder.
@@ -1949,7 +2119,7 @@
 
         /**
          * Specify the value of {@link #visibility}.
-
+         *
          * @param visibility One of {@link #VISIBILITY_PRIVATE} (the default),
          * {@link #VISIBILITY_SECRET}, or {@link #VISIBILITY_PUBLIC}.
          *
@@ -1971,6 +2141,28 @@
             return this;
         }
 
+        /**
+         * Apply an extender to this notification builder. Extenders may be used to add
+         * metadata or change options on this builder.
+         */
+        public Builder apply(Extender extender) {
+            extender.applyTo(this);
+            return this;
+        }
+
+        /**
+         * Extender interface for use with {@link #apply}. Extenders may be used to add
+         * metadata or change options on this builder.
+         */
+        public interface Extender {
+            /**
+             * Apply this extender to a notification builder.
+             * @param builder the builder to be modified.
+             * @return the build object for chaining.
+             */
+            public Builder applyTo(Builder builder);
+        }
+
         private void setFlag(int mask, boolean value) {
             if (value) {
                 mFlags |= mask;
@@ -2298,6 +2490,8 @@
                 n.flags |= FLAG_SHOW_LIGHTS;
             }
             n.category = mCategory;
+            n.mGroupKey = mGroupKey;
+            n.mSortKey = mSortKey;
             n.priority = mPriority;
             if (mActions.size() > 0) {
                 n.actions = new Action[mActions.size()];
diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java
new file mode 100644
index 0000000..9cfc541
--- /dev/null
+++ b/core/java/android/app/RemoteInput.java
@@ -0,0 +1,297 @@
+/*
+ * 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.app;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A {@code RemoteInput} object specifies input to be collected from a user to be passed along with
+ * an intent inside a {@link android.app.PendingIntent} that is sent.
+ * Always use {@link RemoteInput.Builder} to create instances of this class.
+ * <p class="note"> See
+ * <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from
+ * a Notification</a> for more information on how to use this class.
+ *
+ * <p>The following example adds a {@code RemoteInput} to a {@link Notification.Action},
+ * sets the result key as {@code quick_reply}, and sets the label as {@code Quick reply}.
+ * Users are prompted to input a response when they trigger the action. The results are sent along
+ * with the intent and can be retrieved with the result key (provided to the {@link Builder}
+ * constructor) from the Bundle returned by {@link #getResultsFromIntent}.
+ *
+ * <pre class="prettyprint">
+ * public static final String KEY_QUICK_REPLY_TEXT = "quick_reply";
+ * Notification.Action action = new Notification.Action.Builder(
+ *         R.drawable.reply, &quot;Reply&quot;, actionIntent)
+ *         <b>.addRemoteInput(new RemoteInput.Builder(KEY_QUICK_REPLY_TEXT)
+ *                 .setLabel("Quick reply").build()</b>)
+ *         .build();</pre>
+ *
+ * <p>When the {@link android.app.PendingIntent} is fired, the intent inside will contain the
+ * input results if collected. To access these results, use the {@link #getResultsFromIntent}
+ * function. The result values will present under the result key passed to the {@link Builder}
+ * constructor.
+ *
+ * <pre class="prettyprint">
+ * public static final String KEY_QUICK_REPLY_TEXT = "quick_reply";
+ * Bundle results = RemoteInput.getResultsFromIntent(intent);
+ * if (results != null) {
+ *     CharSequence quickReplyResult = results.getCharSequence(KEY_QUICK_REPLY_TEXT);
+ * }</pre>
+ */
+public final class RemoteInput implements Parcelable {
+    /** Label used to denote the clip data type used for remote input transport */
+    public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+
+    /** Extra added to a clip data intent object to hold the results bundle. */
+    public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+
+    private final String mResultKey;
+    private final CharSequence mLabel;
+    private final CharSequence[] mChoices;
+    private final boolean mAllowFreeFormInput;
+    private final Bundle mExtras;
+
+    private RemoteInput(String resultKey, CharSequence label, CharSequence[] choices,
+            boolean allowFreeFormInput, Bundle extras) {
+        this.mResultKey = resultKey;
+        this.mLabel = label;
+        this.mChoices = choices;
+        this.mAllowFreeFormInput = allowFreeFormInput;
+        this.mExtras = extras;
+    }
+
+    /**
+     * Get the key that the result of this input will be set in from the Bundle returned by
+     * {@link #getResultsFromIntent} when the {@link android.app.PendingIntent} is sent.
+     */
+    public String getResultKey() {
+        return mResultKey;
+    }
+
+    /**
+     * Get the label to display to users when collecting this input.
+     */
+    public CharSequence getLabel() {
+        return mLabel;
+    }
+
+    /**
+     * Get possible input choices. This can be {@code null} if there are no choices to present.
+     */
+    public CharSequence[] getChoices() {
+        return mChoices;
+    }
+
+    /**
+     * Get whether or not users can provide an arbitrary value for
+     * input. If you set this to {@code false}, users must select one of the
+     * choices in {@link #getChoices}. An {@link IllegalArgumentException} is thrown
+     * if you set this to false and {@link #getChoices} returns {@code null} or empty.
+     */
+    public boolean getAllowFreeFormInput() {
+        return mAllowFreeFormInput;
+    }
+
+    /**
+     * Get additional metadata carried around with this remote input.
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    /**
+     * Builder class for {@link RemoteInput} objects.
+     */
+    public static final class Builder {
+        private final String mResultKey;
+        private CharSequence mLabel;
+        private CharSequence[] mChoices;
+        private boolean mAllowFreeFormInput = true;
+        private Bundle mExtras = new Bundle();
+
+        /**
+         * Create a builder object for {@link RemoteInput} objects.
+         * @param resultKey the Bundle key that refers to this input when collected from the user
+         */
+        public Builder(String resultKey) {
+            if (resultKey == null) {
+                throw new IllegalArgumentException("Result key can't be null");
+            }
+            mResultKey = resultKey;
+        }
+
+        /**
+         * Set a label to be displayed to the user when collecting this input.
+         * @param label The label to show to users when they input a response.
+         * @return this object for method chaining
+         */
+        public Builder setLabel(CharSequence label) {
+            mLabel = Notification.safeCharSequence(label);
+            return this;
+        }
+
+        /**
+         * Specifies choices available to the user to satisfy this input.
+         * @param choices an array of pre-defined choices for users input.
+         *        You must provide a non-null and non-empty array if
+         *        you disabled free form input using {@link #setAllowFreeFormInput}.
+         * @return this object for method chaining
+         */
+        public Builder setChoices(CharSequence[] choices) {
+            if (choices == null) {
+                mChoices = null;
+            } else {
+                mChoices = new CharSequence[choices.length];
+                for (int i = 0; i < choices.length; i++) {
+                    mChoices[i] = Notification.safeCharSequence(choices[i]);
+                }
+            }
+            return this;
+        }
+
+        /**
+         * Specifies whether the user can provide arbitrary values.
+         *
+         * @param allowFreeFormInput The default is {@code true}.
+         *         If you specify {@code false}, you must provide a non-null
+         *         and non-empty array to {@link #setChoices} or an
+         *         {@link IllegalArgumentException} is thrown.
+         * @return this object for method chaining
+         */
+        public Builder setAllowFreeFormInput(boolean allowFreeFormInput) {
+            mAllowFreeFormInput = allowFreeFormInput;
+            return this;
+        }
+
+        /**
+         * Merge additional metadata into this builder.
+         *
+         * <p>Values within the Bundle will replace existing extras values in this Builder.
+         *
+         * @see RemoteInput#getExtras
+         */
+        public Builder addExtras(Bundle extras) {
+            if (extras != null) {
+                mExtras.putAll(extras);
+            }
+            return this;
+        }
+
+        /**
+         * Get the metadata Bundle used by this Builder.
+         *
+         * <p>The returned Bundle is shared with this Builder.
+         */
+        public Bundle getExtras() {
+            return mExtras;
+        }
+
+        /**
+         * Combine all of the options that have been set and return a new {@link RemoteInput}
+         * object.
+         */
+        public RemoteInput build() {
+            return new RemoteInput(mResultKey, mLabel, mChoices, mAllowFreeFormInput, mExtras);
+        }
+    }
+
+    private RemoteInput(Parcel in) {
+        mResultKey = in.readString();
+        mLabel = in.readCharSequence();
+        mChoices = in.readCharSequenceArray();
+        mAllowFreeFormInput = in.readInt() != 0;
+        mExtras = in.readBundle();
+    }
+
+    /**
+     * Get the remote input results bundle from an intent. The returned Bundle will
+     * contain a key/value for every result key populated by remote input collector.
+     * Use the {@link Bundle#getCharSequence(String)} method to retrieve a value.
+     * @param intent The intent object that fired in response to an action or content intent
+     *               which also had one or more remote input requested.
+     */
+    public static Bundle getResultsFromIntent(Intent intent) {
+        ClipData clipData = intent.getClipData();
+        if (clipData == null) {
+            return null;
+        }
+        ClipDescription clipDescription = clipData.getDescription();
+        if (!clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) {
+            return null;
+        }
+        if (clipDescription.getLabel().equals(RESULTS_CLIP_LABEL)) {
+            return clipData.getItemAt(0).getIntent().getExtras().getParcelable(EXTRA_RESULTS_DATA);
+        }
+        return null;
+    }
+
+    /**
+     * Populate an intent object with the results gathered from remote input. This method
+     * should only be called by remote input collection services when sending results to a
+     * pending intent.
+     * @param remoteInputs The remote inputs for which results are being provided
+     * @param intent The intent to add remote inputs to. The {@link ClipData}
+     *               field of the intent will be modified to contain the results.
+     * @param results A bundle holding the remote input results. This bundle should
+     *                be populated with keys matching the result keys specified in
+     *                {@code remoteInputs} with values being the result per key.
+     */
+    public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,
+            Bundle results) {
+        Bundle resultsBundle = new Bundle();
+        for (RemoteInput remoteInput : remoteInputs) {
+            Object result = results.get(remoteInput.getResultKey());
+            if (result instanceof CharSequence) {
+                resultsBundle.putCharSequence(remoteInput.getResultKey(), (CharSequence) result);
+            }
+        }
+        Intent clipIntent = new Intent();
+        clipIntent.putExtra(EXTRA_RESULTS_DATA, resultsBundle);
+        intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipIntent));
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mResultKey);
+        out.writeCharSequence(mLabel);
+        out.writeCharSequenceArray(mChoices);
+        out.writeInt(mAllowFreeFormInput ? 1 : 0);
+        out.writeBundle(mExtras);
+    }
+
+    public static final Creator<RemoteInput> CREATOR = new Creator<RemoteInput>() {
+        @Override
+        public RemoteInput createFromParcel(Parcel in) {
+            return new RemoteInput(in);
+        }
+
+        @Override
+        public RemoteInput[] newArray(int size) {
+            return new RemoteInput[size];
+        }
+    };
+}
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index f9d9059..ee222a9 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -166,12 +166,11 @@
 
     /**
      * Broadcast Action: This broadcast is sent to the newly created profile when
-     * the provisioning of a managed profile has completed successfully.
+     * the provisioning of a managed profile has completed successfully. It is used in both the
+     * Profile Owner and the Device Owner provisioning.
      *
-     * <p>The broadcast is limited to the package which started the provisioning as specified in
-     * the extra {@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} of the
-     * {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the
-     * provisioning. It is also limited to the managed profile.
+     * <p>The broadcast is limited to the DeviceAdminReceiver component specified in the message
+     * that started the provisioning. It is also limited to the managed profile.
      *
      * <p>Input: Nothing.</p>
      * <p>Output: Nothing</p>
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8884446..18e2a95 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -32,6 +32,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.trust.TrustAgentService;
 import android.util.Log;
 
@@ -2050,6 +2051,68 @@
     }
 
     /**
+     * Called by device or profile owner to block or unblock packages. When a package is blocked it
+     * is unavailable for use, but the data and actual package file remain.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName The name of the package to block or unblock.
+     * @param blocked {@code true} if the package should be blocked, {@code false} if it should be
+     *                 unblocked.
+     * @return boolean Whether the blocked setting of the package was successfully updated.
+     */
+    public boolean setApplicationBlocked(ComponentName admin, String packageName,
+            boolean blocked) {
+        if (mService != null) {
+            try {
+                return mService.setApplicationBlocked(admin, packageName, blocked);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Called by profile or device owner to block or unblock currently installed packages. This
+     * should only be called by a profile or device owner running within a managed profile.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param intent An intent matching the app(s) to be updated. All apps that resolve for this
+     *               intent will be updated in the current profile.
+     * @param blocked {@code true} if the packages should be blocked, {@code false} if they should
+     *                 be unblocked.
+     * @return int The number of activities that matched the intent and were updated.
+     */
+    public int setApplicationsBlocked(ComponentName admin, Intent intent, boolean blocked) {
+        if (mService != null) {
+            try {
+                return mService.setApplicationsBlocked(admin, intent, blocked);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Called by device or profile owner to determine if a package is blocked.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName The name of the package to retrieve the blocked status of.
+     * @return boolean {@code true} if the package is blocked, {@code false} otherwise.
+     */
+    public boolean isApplicationBlocked(ComponentName admin, String packageName) {
+        if (mService != null) {
+            try {
+                return mService.isApplicationBlocked(admin, packageName);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Called by profile or device owner to re-enable a system app that was disabled by default
      * when the managed profile was created. This should only be called from a profile or device
      * owner running within a managed profile.
@@ -2181,4 +2244,42 @@
         }
         return false;
     }
+
+    /**
+     * Called by device owners to update {@link Settings.Global} settings. Validation that the value
+     * of the setting is in the correct form for the setting type should be performed by the caller.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param setting The name of the setting to update.
+     * @param value The value to update the setting to.
+     */
+    public void setGlobalSetting(ComponentName admin, String setting, String value) {
+        if (mService != null) {
+            try {
+                mService.setGlobalSetting(admin, setting, value);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Called by profile or device owners to update {@link Settings.Secure} settings. Validation
+     * that the value of the setting is in the correct form for the setting type should be performed
+     * by the caller.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param setting The name of the setting to update.
+     * @param value The value to update the setting to.
+     */
+    public void setSecureSetting(ComponentName admin, String setting, String value) {
+        if (mService != null) {
+            try {
+                mService.setSecureSetting(admin, setting, value);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 03ced0f..7257158 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -124,6 +124,10 @@
     void addForwardingIntentFilter(in ComponentName admin, in IntentFilter filter, int flags);
     void clearForwardingIntentFilters(in ComponentName admin);
 
+    boolean setApplicationBlocked(in ComponentName admin, in String packageName, boolean blocked);
+    int setApplicationsBlocked(in ComponentName admin, in Intent intent, boolean blocked);
+    boolean isApplicationBlocked(in ComponentName admin, in String packageName);
+
     void enableSystemApp(in ComponentName admin, in String packageName);
     int enableSystemAppWithIntent(in ComponentName admin, in Intent intent);
 
@@ -133,4 +137,7 @@
     void setLockTaskComponents(in ComponentName[] components);
     ComponentName[] getLockTaskComponents();
     boolean isLockTaskPermitted(in ComponentName component);
+
+    void setGlobalSetting(in ComponentName who, in String setting, in String value);
+    void setSecureSetting(in ComponentName who, in String setting, in String value);
 }
diff --git a/core/java/android/app/wearable/WearableActionExtensions.java b/core/java/android/app/wearable/WearableActionExtensions.java
new file mode 100644
index 0000000..c296ef2
--- /dev/null
+++ b/core/java/android/app/wearable/WearableActionExtensions.java
@@ -0,0 +1,176 @@
+/*
+ * 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.app.wearable;
+
+import android.app.Notification;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Wearable extensions to notification actions. To add extensions to an action,
+ * create a new {@link WearableActionExtensions} object using
+ * {@link WearableActionExtensions.Builder} and apply it to a
+ * {@link android.app.Notification.Action.Builder}.
+ *
+ * <pre class="prettyprint">
+ * Notification.Action action = new Notification.Action.Builder(
+ *         R.drawable.archive_all, "Archive all", actionIntent)
+ *         .apply(new WearableActionExtensions.Builder()
+ *                 .setAvailableOffline(false)
+ *                 .build())
+ *         .build();
+ * </pre>
+ */
+public final class WearableActionExtensions implements Notification.Action.Builder.Extender,
+        Parcelable {
+    /** Notification action extra which contains wearable extensions */
+    private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS";
+
+    // Flags bitwise-ored to mFlags
+    private static final int FLAG_AVAILABLE_OFFLINE = 1 << 0;
+
+    // Default value for flags integer
+    private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE;
+
+    private final int mFlags;
+
+    private WearableActionExtensions(int flags) {
+        mFlags = flags;
+    }
+
+    private WearableActionExtensions(Parcel in) {
+        mFlags = in.readInt();
+    }
+
+    /**
+     * Create a {@link WearableActionExtensions} by reading wearable extensions present on an
+     * existing notification action.
+     * @param action the notification action to inspect.
+     * @return a new {@link WearableActionExtensions} object.
+     */
+    public static WearableActionExtensions from(Notification.Action action) {
+        WearableActionExtensions extensions = action.getExtras().getParcelable(
+                EXTRA_WEARABLE_EXTENSIONS);
+        if (extensions != null) {
+            return extensions;
+        } else {
+            // Return a WearableActionExtensions with default values.
+            return new Builder().build();
+        }
+    }
+
+    /**
+     * Get whether this action is available when the wearable device is not connected to
+     * a companion device. The user can still trigger this action when the wearable device is
+     * offline, but a visual hint will indicate that the action may not be available.
+     * Defaults to true.
+     */
+    public boolean isAvailableOffline() {
+        return (mFlags & FLAG_AVAILABLE_OFFLINE) != 0;
+    }
+
+    @Override
+    public Notification.Action.Builder applyTo(Notification.Action.Builder builder) {
+        builder.getExtras().putParcelable(EXTRA_WEARABLE_EXTENSIONS, this);
+        return builder;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mFlags);
+    }
+
+    /**
+     * Builder for {@link WearableActionExtensions} objects, which adds wearable extensions to
+     * notification actions. To extend an action, create an instance of this class, call the set
+     * methods present, call {@link #build}, and finally apply the options to a
+     * {@link Notification.Action.Builder} using its
+     * {@link android.app.Notification.Action.Builder#apply} method.
+     */
+    public static final class Builder {
+        private int mFlags = DEFAULT_FLAGS;
+
+        /**
+         * Construct a builder to be used for adding wearable extensions to notification actions.
+         *
+         * <pre class="prettyprint">
+         * Notification.Action action = new Notification.Action.Builder(
+         *         R.drawable.archive_all, "Archive all", actionIntent)
+         *         .apply(new WearableActionExtensions.Builder()
+         *                 .setAvailableOffline(false)
+         *                 .build())
+         *         .build();</pre>
+         */
+        public Builder() {
+        }
+
+        /**
+         * Create a {@link Builder} by reading wearable extensions present on an
+         * existing {@code WearableActionExtensions} object.
+         * @param other the existing extensions to inspect.
+         */
+        public Builder(WearableActionExtensions other) {
+            mFlags = other.mFlags;
+        }
+
+        /**
+         * Set whether this action is available when the wearable device is not connected to
+         * a companion device. The user can still trigger this action when the wearable device is
+         * offline, but a visual hint will indicate that the action may not be available.
+         * Defaults to true.
+         */
+        public Builder setAvailableOffline(boolean availableOffline) {
+            setFlag(FLAG_AVAILABLE_OFFLINE, availableOffline);
+            return this;
+        }
+
+        /**
+         * Build a new {@link WearableActionExtensions} object with the extensions
+         * currently present on this builder.
+         * @return the extensions object.
+         */
+        public WearableActionExtensions build() {
+            return new WearableActionExtensions(mFlags);
+        }
+
+        private void setFlag(int mask, boolean value) {
+            if (value) {
+                mFlags |= mask;
+            } else {
+                mFlags &= ~mask;
+            }
+        }
+    }
+
+    public static final Creator<WearableActionExtensions> CREATOR =
+            new Creator<WearableActionExtensions>() {
+        @Override
+        public WearableActionExtensions createFromParcel(Parcel in) {
+            return new WearableActionExtensions(in);
+        }
+
+        @Override
+        public WearableActionExtensions[] newArray(int size) {
+            return new WearableActionExtensions[size];
+        }
+    };
+}
diff --git a/core/java/android/app/wearable/WearableNotificationExtensions.java b/core/java/android/app/wearable/WearableNotificationExtensions.java
new file mode 100644
index 0000000..d433613
--- /dev/null
+++ b/core/java/android/app/wearable/WearableNotificationExtensions.java
@@ -0,0 +1,702 @@
+/*
+ * 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.app.wearable;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.Gravity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Helper class that contains wearable extensions for notifications.
+ * <p class="note"> See
+ * <a href="{@docRoot}wear/notifications/creating.html">Creating Notifications
+ * for Android Wear</a> for more information on how to use this class.
+ * <p>
+ * To create a notification with wearable extensions:
+ * <ol>
+ *   <li>Create a {@link Notification.Builder}, setting any desired
+ *   properties.
+ *   <li>Create a {@link WearableNotificationExtensions.Builder}.
+ *   <li>Set wearable-specific properties using the
+ *   {@code add} and {@code set} methods of {@link WearableNotificationExtensions.Builder}.
+ *   <li>Call {@link WearableNotificationExtensions.Builder#build} to build the extensions
+ *   object.
+ *   <li>Call {@link Notification.Builder#apply} to apply the extensions to a notification.
+ *   <li>Post the notification to the notification system with the
+ *   {@code NotificationManager.notify(...)} methods.
+ * </ol>
+ *
+ * <pre class="prettyprint">
+ * Notification notif = new Notification.Builder(mContext)
+ *         .setContentTitle(&quot;New mail from &quot; + sender.toString())
+ *         .setContentText(subject)
+ *         .setSmallIcon(R.drawable.new_mail)
+ *         .apply(new new WearableNotificationExtensions.Builder()
+ *                 .setContentIcon(R.drawable.new_mail)
+ *                 .build())
+ *         .build();
+ * NotificationManager notificationManger =
+ *         (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ * notificationManger.notify(0, notif);</pre>
+ *
+ * <p>Wearable extensions can be accessed on an existing notification by using the
+ * {@link WearableNotificationExtensions#from} function.
+ *
+ * <pre class="prettyprint">
+ * WearableNotificationExtensions wearableExtensions = WearableNotificationExtensions.from(
+ *         notification);
+ * Notification[] pages = wearableExtensions.getPages();
+ * </pre>
+ */
+public final class WearableNotificationExtensions implements Notification.Builder.Extender,
+        Parcelable {
+    /**
+     * Sentinel value for an action index that is unset.
+     */
+    public static final int UNSET_ACTION_INDEX = -1;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification with
+     * default sizing.
+     * <p>For custom display notifications created using {@link Builder#setDisplayIntent},
+     * the default is {@link #SIZE_LARGE}. All other notifications size automatically based
+     * on their content.
+     */
+    public static final int SIZE_DEFAULT = 0;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+     * with an extra small size.
+     * <p>This value is only applicable for custom display notifications created using
+     * {@link Builder#setDisplayIntent}.
+     */
+    public static final int SIZE_XSMALL = 1;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+     * with a small size.
+     * <p>This value is only applicable for custom display notifications created using
+     * {@link Builder#setDisplayIntent}.
+     */
+    public static final int SIZE_SMALL = 2;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+     * with a medium size.
+     * <p>This value is only applicable for custom display notifications created using
+     * {@link Builder#setDisplayIntent}.
+     */
+    public static final int SIZE_MEDIUM = 3;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+     * with a large size.
+     * <p>This value is only applicable for custom display notifications created using
+     * {@link Builder#setDisplayIntent}.
+     */
+    public static final int SIZE_LARGE = 4;
+
+    /** Notification extra which contains wearable extensions */
+    static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS";
+
+    // Flags bitwise-ored to mFlags
+    static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 1 << 0;
+    static final int FLAG_HINT_HIDE_ICON = 1 << 1;
+    static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2;
+    static final int FLAG_START_SCROLL_BOTTOM = 1 << 3;
+
+    // Default value for flags integer
+    static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE;
+
+    private final Notification.Action[] mActions;
+    private final int mFlags;
+    private final PendingIntent mDisplayIntent;
+    private final Notification[] mPages;
+    private final Bitmap mBackground;
+    private final int mContentIcon;
+    private final int mContentIconGravity;
+    private final int mContentActionIndex;
+    private final int mCustomSizePreset;
+    private final int mCustomContentHeight;
+    private final int mGravity;
+
+    private WearableNotificationExtensions(Notification.Action[] actions, int flags,
+            PendingIntent displayIntent, Notification[] pages, Bitmap background,
+            int contentIcon, int contentIconGravity, int contentActionIndex,
+            int customSizePreset, int customContentHeight, int gravity) {
+        mActions = actions;
+        mFlags = flags;
+        mDisplayIntent = displayIntent;
+        mPages = pages;
+        mBackground = background;
+        mContentIcon = contentIcon;
+        mContentIconGravity = contentIconGravity;
+        mContentActionIndex = contentActionIndex;
+        mCustomSizePreset = customSizePreset;
+        mCustomContentHeight = customContentHeight;
+        mGravity = gravity;
+    }
+
+    private WearableNotificationExtensions(Parcel in) {
+        mActions = in.createTypedArray(Notification.Action.CREATOR);
+        mFlags = in.readInt();
+        mDisplayIntent = in.readParcelable(PendingIntent.class.getClassLoader());
+        mPages = in.createTypedArray(Notification.CREATOR);
+        mBackground = in.readParcelable(Bitmap.class.getClassLoader());
+        mContentIcon = in.readInt();
+        mContentIconGravity = in.readInt();
+        mContentActionIndex = in.readInt();
+        mCustomSizePreset = in.readInt();
+        mCustomContentHeight = in.readInt();
+        mGravity = in.readInt();
+    }
+
+    /**
+     * Create a {@link WearableNotificationExtensions} by reading wearable extensions present on an
+     * existing notification.
+     * @param notif the notification to inspect.
+     * @return a new {@link WearableNotificationExtensions} object.
+     */
+    public static WearableNotificationExtensions from(Notification notif) {
+        WearableNotificationExtensions extensions = notif.extras.getParcelable(
+                EXTRA_WEARABLE_EXTENSIONS);
+        if (extensions != null) {
+            return extensions;
+        } else {
+            // Return a WearableNotificationExtensions with default values.
+            return new Builder().build();
+        }
+    }
+
+    /**
+     * Apply wearable extensions to a notification that is being built. This is typically
+     * called by {@link Notification.Builder#apply} method of {@link Notification.Builder}.
+     */
+    @Override
+    public Notification.Builder applyTo(Notification.Builder builder) {
+        builder.getExtras().putParcelable(EXTRA_WEARABLE_EXTENSIONS, this);
+        return builder;
+    }
+
+    /**
+     * Get the number of wearable actions present on this notification.
+     *
+     * @return the number of wearable actions for this notification
+     */
+    public int getActionCount() {
+        return mActions.length;
+    }
+
+    /**
+     * Get a {@link Notification.Action} for the wearable action at {@code actionIndex}.
+     * @param actionIndex the index of the desired wearable action
+     */
+    public Notification.Action getAction(int actionIndex) {
+        return mActions[actionIndex];
+    }
+
+    /**
+     * Get the wearable actions present on this notification.
+     */
+    public Notification.Action[] getActions() {
+        return mActions;
+    }
+
+    /**
+     * Get the intent to launch inside of an activity view when displaying this
+     * notification. This {@code PendingIntent} should be for an activity.
+     */
+    public PendingIntent getDisplayIntent() {
+        return mDisplayIntent;
+    }
+
+    /**
+     * Get the array of additional pages of content for displaying this notification. The
+     * current notification forms the first page, and elements within this array form
+     * subsequent pages. This field can be used to separate a notification into multiple
+     * sections.
+     * @return the pages for this notification
+     */
+    public Notification[] getPages() {
+        return mPages;
+    }
+
+    /**
+     * Get a background image to be displayed behind the notification content.
+     * Contrary to the {@link Notification.BigPictureStyle}, this background
+     * will work with any notification style.
+     *
+     * @return the background image
+     * @see Builder#setBackground
+     */
+    public Bitmap getBackground() {
+        return mBackground;
+    }
+
+    /**
+     * Get an icon that goes with the content of this notification.
+     */
+    public int getContentIcon() {
+        return mContentIcon;
+    }
+
+    /**
+     * Get the gravity that the content icon should have within the notification display.
+     * Supported values include {@link Gravity#START} and {@link Gravity#END}. The default
+     * value is {@link android.view.Gravity#END}.
+     * @see #getContentIcon
+     */
+    public int getContentIconGravity() {
+        return mContentIconGravity;
+    }
+
+    /**
+     * Get the action index of an action from this notification to show as clickable with
+     * the content of this notification page. When the user clicks this notification page,
+     * this action will trigger. This action will no longer display separately from the
+     * notification content. The action's icon will display with optional subtext provided
+     * by the action's title.
+     *
+     * <p>If wearable specific actions are present, this index will apply to that list,
+     * otherwise it will apply to the main notification's actions list.
+     */
+    public int getContentAction() {
+        return mContentActionIndex;
+    }
+
+    /**
+     * Get the gravity that this notification should have within the available viewport space.
+     * Supported values include {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL} and
+     * {@link android.view.Gravity#BOTTOM}. The default value is
+     * {@link android.view.Gravity#BOTTOM}.
+     */
+    public int getGravity() {
+        return mGravity;
+    }
+
+    /**
+     * Get the custom size preset for the display of this notification out of the available
+     * presets found in {@link WearableNotificationExtensions}, e.g. {@link #SIZE_LARGE}.
+     * <p>Some custom size presets are only applicable for custom display notifications created
+     * using {@link Builder#setDisplayIntent}. Check the documentation for the preset in question.
+     * See also {@link Builder#setCustomContentHeight} and {@link Builder#setCustomSizePreset}.
+     */
+    public int getCustomSizePreset() {
+        return mCustomSizePreset;
+    }
+
+    /**
+     * Get the custom height in pixels for the display of this notification's content.
+     * <p>This option is only available for custom display notifications created
+     * using {@link Builder#setDisplayIntent}. See also {@link Builder#setCustomSizePreset} and
+     * {@link Builder#setCustomContentHeight}.
+     */
+    public int getCustomContentHeight() {
+        return mCustomContentHeight;
+    }
+
+    /**
+     * Get whether the scrolling position for the contents of this notification should start
+     * at the bottom of the contents instead of the top when the contents are too long to
+     * display within the screen. Default is false (start scroll at the top).
+     */
+    public boolean getStartScrollBottom() {
+        return (mFlags & FLAG_START_SCROLL_BOTTOM) != 0;
+    }
+
+    /**
+     * Get whether the content intent is available when the wearable device is not connected
+     * to a companion device.  The user can still trigger this intent when the wearable device is
+     * offline, but a visual hint will indicate that the content intent may not be available.
+     * Defaults to true.
+     */
+    public boolean getContentIntentAvailableOffline() {
+        return (mFlags & FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE) != 0;
+    }
+
+    /**
+     * Get a hint that this notification's icon should not be displayed.
+     * @return {@code true} if this icon should not be displayed, false otherwise.
+     * The default value is {@code false} if this was never set.
+     */
+    public boolean getHintHideIcon() {
+        return (mFlags & FLAG_HINT_HIDE_ICON) != 0;
+    }
+
+    /**
+     * Get a visual hint that only the background image of this notification should be
+     * displayed, and other semantic content should be hidden. This hint is only applicable
+     * to sub-pages added using {@link Builder#addPage}.
+     */
+    public boolean getHintShowBackgroundOnly() {
+        return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeTypedArray(mActions, flags);
+        out.writeInt(mFlags);
+        out.writeParcelable(mDisplayIntent, flags);
+        out.writeTypedArray(mPages, flags);
+        out.writeParcelable(mBackground, flags);
+        out.writeInt(mContentIcon);
+        out.writeInt(mContentIconGravity);
+        out.writeInt(mContentActionIndex);
+        out.writeInt(mCustomSizePreset);
+        out.writeInt(mCustomContentHeight);
+        out.writeInt(mGravity);
+    }
+
+    /**
+     * Builder to apply wearable notification extensions to a {@link Notification.Builder}
+     * object.
+     *
+     * <p>You can chain the "set" methods for this builder in any order,
+     * but you must call the {@link #build} method and then the {@link Notification.Builder#apply}
+     * method to apply your extensions to a notification.
+     *
+     * <pre class="prettyprint">
+     * Notification notif = new Notification.Builder(mContext)
+     *         .setContentTitle(&quot;New mail from &quot; + sender.toString())
+     *         .setContentText(subject)
+     *         .setSmallIcon(R.drawable.new_mail);
+     *         .apply(new WearableNotificationExtensions.Builder()
+     *                 .setContentIcon(R.drawable.new_mail)
+     *                 .build())
+     *         .build();
+     * NotificationManager notificationManger =
+     *         (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+     * notificationManager.notify(0, notif);</pre>
+     */
+    public static final class Builder {
+        private final List<Notification.Action> mActions =
+                new ArrayList<Notification.Action>();
+        private int mFlags = DEFAULT_FLAGS;
+        private PendingIntent mDisplayIntent;
+        private final List<Notification> mPages = new ArrayList<Notification>();
+        private Bitmap mBackground;
+        private int mContentIcon;
+        private int mContentIconGravity = Gravity.END;
+        private int mContentActionIndex = UNSET_ACTION_INDEX;
+        private int mCustomContentHeight;
+        private int mCustomSizePreset = SIZE_DEFAULT;
+        private int mGravity = Gravity.BOTTOM;
+
+        /**
+         * Construct a builder to be used for adding wearable extensions to notifications.
+         *
+         * <pre class="prettyprint">
+         * Notification notif = new Notification.Builder(mContext)
+         *         .setContentTitle(&quot;New mail from &quot; + sender.toString())
+         *         .setContentText(subject)
+         *         .setSmallIcon(R.drawable.new_mail);
+         *         .apply(new WearableNotificationExtensions.Builder()
+         *                 .setContentIcon(R.drawable.new_mail)
+         *                 .build())
+         *         .build();
+         * NotificationManager notificationManger =
+         *         (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+         * notificationManager.notify(0, notif);</pre>
+         */
+        public Builder() {
+        }
+
+        /**
+         * Create a {@link Builder} by reading wearable extensions present on an
+         * existing {@code WearableNotificationExtensions} object.
+         * @param other the existing extensions to inspect.
+         */
+        public Builder(WearableNotificationExtensions other) {
+            Collections.addAll(mActions, other.mActions);
+            mFlags = other.mFlags;
+            mDisplayIntent = other.mDisplayIntent;
+            Collections.addAll(mPages, other.mPages);
+            mBackground = other.mBackground;
+            mContentIcon = other.mContentIcon;
+            mContentIconGravity = other.mContentIconGravity;
+            mContentActionIndex = other.mContentActionIndex;
+            mCustomContentHeight = other.mCustomContentHeight;
+            mCustomSizePreset = other.mCustomSizePreset;
+            mGravity = other.mGravity;
+        }
+
+        /**
+         * Add a wearable action to this notification.
+         *
+         * <p>When wearable actions are added using this method, the set of actions that
+         * show on a wearable device splits from devices that only show actions added
+         * using {@link android.app.Notification.Builder#addAction}. This allows for customization
+         * of which actions display on different devices.
+         *
+         * @param action the action to add to this notification
+         * @return this object for method chaining
+         * @see Notification.Action
+         */
+        public Builder addAction(Notification.Action action) {
+            mActions.add(action);
+            return this;
+        }
+
+        /**
+         * Adds wearable actions to this notification.
+         *
+         * <p>When wearable actions are added using this method, the set of actions that
+         * show on a wearable device splits from devices that only show actions added
+         * using {@link android.app.Notification.Builder#addAction}. This allows for customization
+         * of which actions display on different devices.
+         *
+         * @param actions the actions to add to this notification
+         * @return this object for method chaining
+         * @see Notification.Action
+         */
+        public Builder addActions(List<Notification.Action> actions) {
+            mActions.addAll(actions);
+            return this;
+        }
+
+        /**
+         * Clear all wearable actions present on this builder.
+         * @return this object for method chaining.
+         * @see #addAction
+         */
+        public Builder clearActions() {
+            mActions.clear();
+            return this;
+        }
+
+        /**
+         * Set an intent to launch inside of an activity view when displaying
+         * this notification. This {@link android.app.PendingIntent} should be for an activity.
+         *
+         * @param intent the {@link android.app.PendingIntent} for an activity
+         * @return this object for method chaining
+         * @see WearableNotificationExtensions#getDisplayIntent
+         */
+        public Builder setDisplayIntent(PendingIntent intent) {
+            mDisplayIntent = intent;
+            return this;
+        }
+
+        /**
+         * Add an additional page of content to display with this notification. The current
+         * notification forms the first page, and pages added using this function form
+         * subsequent pages. This field can be used to separate a notification into multiple
+         * sections.
+         *
+         * @param page the notification to add as another page
+         * @return this object for method chaining
+         * @see WearableNotificationExtensions#getPages
+         */
+        public Builder addPage(Notification page) {
+            mPages.add(page);
+            return this;
+        }
+
+        /**
+         * Add additional pages of content to display with this notification. The current
+         * notification forms the first page, and pages added using this function form
+         * subsequent pages. This field can be used to separate a notification into multiple
+         * sections.
+         *
+         * @param pages a list of notifications
+         * @return this object for method chaining
+         * @see WearableNotificationExtensions#getPages
+         */
+        public Builder addPages(List<Notification> pages) {
+            mPages.addAll(pages);
+            return this;
+        }
+
+        /**
+         * Clear all additional pages present on this builder.
+         * @return this object for method chaining.
+         * @see #addPage
+         */
+        public Builder clearPages() {
+            mPages.clear();
+            return this;
+        }
+
+        /**
+         * Set a background image to be displayed behind the notification content.
+         * Contrary to the {@link Notification.BigPictureStyle}, this background
+         * will work with any notification style.
+         *
+         * @param background the background bitmap
+         * @return this object for method chaining
+         * @see WearableNotificationExtensions#getBackground
+         */
+        public Builder setBackground(Bitmap background) {
+            mBackground = background;
+            return this;
+        }
+
+        /**
+         * Set an icon that goes with the content of this notification.
+         */
+        public Builder setContentIcon(int icon) {
+            mContentIcon = icon;
+            return this;
+        }
+
+        /**
+         * Set the gravity that the content icon should have within the notification display.
+         * Supported values include {@link Gravity#START} and {@link Gravity#END}. The default
+         * value is {@link android.view.Gravity#END}.
+         * @see #setContentIcon
+         */
+        public Builder setContentIconGravity(int contentIconGravity) {
+            mContentIconGravity = contentIconGravity;
+            return this;
+        }
+
+        /**
+         * Set an action from this notification's actions to be clickable with the content of
+         * this notification page. This action will no longer display separately from the
+         * notification content. This action's icon will display with optional subtext provided
+         * by the action's title.
+         * @param actionIndex The index of the action to hoist on the current notification page.
+         *                    If wearable actions are present, this index will apply to that list,
+         *                    otherwise it will apply to the main notification's actions list.
+         */
+        public Builder setContentAction(int actionIndex) {
+            mContentActionIndex = actionIndex;
+            return this;
+        }
+
+        /**
+         * Set the gravity that this notification should have within the available viewport space.
+         * Supported values include {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL} and
+         * {@link Gravity#BOTTOM}. The default value is {@link Gravity#BOTTOM}.
+         */
+        public Builder setGravity(int gravity) {
+            mGravity = gravity;
+            return this;
+        }
+
+        /**
+         * Set the custom size preset for the display of this notification out of the available
+         * presets found in {@link WearableNotificationExtensions}, e.g. {@link #SIZE_LARGE}.
+         * <p>Some custom size presets are only applicable for custom display notifications created
+         * using {@link Builder#setDisplayIntent}. Check the documentation for the preset in
+         * question. See also {@link Builder#setCustomContentHeight} and
+         * {@link #getCustomSizePreset}.
+         */
+        public Builder setCustomSizePreset(int sizePreset) {
+            mCustomSizePreset = sizePreset;
+            return this;
+        }
+
+        /**
+         * Set the custom height in pixels for the display of this notification's content.
+         * <p>This option is only available for custom display notifications created
+         * using {@link Builder#setDisplayIntent}. See also {@link Builder#setCustomSizePreset} and
+         * {@link #getCustomContentHeight}.
+         */
+        public Builder setCustomContentHeight(int height) {
+            mCustomContentHeight = height;
+            return this;
+        }
+
+        /**
+         * Set whether the scrolling position for the contents of this notification should start
+         * at the bottom of the contents instead of the top when the contents are too long to
+         * display within the screen.  Default is false (start scroll at the top).
+         */
+        public Builder setStartScrollBottom(boolean startScrollBottom) {
+            setFlag(FLAG_START_SCROLL_BOTTOM, startScrollBottom);
+            return this;
+        }
+
+        /**
+         * Set whether the content intent is available when the wearable device is not connected
+         * to a companion device.  The user can still trigger this intent when the wearable device
+         * is offline, but a visual hint will indicate that the content intent may not be available.
+         * Defaults to true.
+         */
+        public Builder setContentIntentAvailableOffline(boolean contentIntentAvailableOffline) {
+            setFlag(FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE, contentIntentAvailableOffline);
+            return this;
+        }
+
+        /**
+         * Set a hint that this notification's icon should not be displayed.
+         * @param hintHideIcon {@code true} to hide the icon, {@code false} otherwise.
+         * @return this object for method chaining
+         */
+        public Builder setHintHideIcon(boolean hintHideIcon) {
+            setFlag(FLAG_HINT_HIDE_ICON, hintHideIcon);
+            return this;
+        }
+
+        /**
+         * Set a visual hint that only the background image of this notification should be
+         * displayed, and other semantic content should be hidden. This hint is only applicable
+         * to sub-pages added using {@link #addPage}.
+         */
+        public Builder setHintShowBackgroundOnly(boolean hintShowBackgroundOnly) {
+            setFlag(FLAG_HINT_SHOW_BACKGROUND_ONLY, hintShowBackgroundOnly);
+            return this;
+        }
+
+        /**
+         * Build a new {@link WearableNotificationExtensions} object with the extensions
+         * currently present on this builder.
+         * @return the extensions object.
+         */
+        public WearableNotificationExtensions build() {
+            return new WearableNotificationExtensions(
+                    mActions.toArray(new Notification.Action[mActions.size()]), mFlags,
+                    mDisplayIntent, mPages.toArray(new Notification[mPages.size()]),
+                    mBackground, mContentIcon, mContentIconGravity, mContentActionIndex,
+                    mCustomSizePreset, mCustomContentHeight, mGravity);
+        }
+
+        private void setFlag(int mask, boolean value) {
+            if (value) {
+                mFlags |= mask;
+            } else {
+                mFlags &= ~mask;
+            }
+        }
+    }
+
+    public static final Creator<WearableNotificationExtensions> CREATOR =
+            new Creator<WearableNotificationExtensions>() {
+        @Override
+        public WearableNotificationExtensions createFromParcel(Parcel in) {
+            return new WearableNotificationExtensions(in);
+        }
+
+        @Override
+        public WearableNotificationExtensions[] newArray(int size) {
+            return new WearableNotificationExtensions[size];
+        }
+    };
+}
diff --git a/core/java/android/bluetooth/BluetoothLeAdvertiseScanData.java b/core/java/android/bluetooth/BluetoothLeAdvertiseScanData.java
index d12ac6c..2fa5e49 100644
--- a/core/java/android/bluetooth/BluetoothLeAdvertiseScanData.java
+++ b/core/java/android/bluetooth/BluetoothLeAdvertiseScanData.java
@@ -53,9 +53,6 @@
      * Bluetooth LE scan response data, the data will be placed in ScanRspData field of advertising
      * packet.
      * <p>
-     * TODO: unhide when stack supports setting scan response data.
-     *
-     * @hide
      */
     public static final int SCAN_RESPONSE_DATA = 1;
     /**
diff --git a/core/java/android/bluetooth/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/BluetoothLeAdvertiser.java
index 2a8aa23..30c90c4 100644
--- a/core/java/android/bluetooth/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/BluetoothLeAdvertiser.java
@@ -328,6 +328,7 @@
         private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000;
         private final AdvertiseCallback mAdvertiseCallback;
         private final AdvertisementData mAdvertisement;
+        private final AdvertisementData mScanResponse;
         private final Settings mSettings;
         private final IBluetoothGatt mBluetoothGatt;
 
@@ -338,10 +339,11 @@
         private boolean isAdvertising = false;
 
         public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback,
-                AdvertisementData advertiseData, Settings settings,
+                AdvertisementData advertiseData, AdvertisementData scanResponse, Settings settings,
                 IBluetoothGatt bluetoothGatt) {
             mAdvertiseCallback = advertiseCallback;
             mAdvertisement = advertiseData;
+            mScanResponse = scanResponse;
             mSettings = settings;
             mBluetoothGatt = bluetoothGatt;
             mLeHandle = 0;
@@ -384,7 +386,8 @@
                 if (status == BluetoothGatt.GATT_SUCCESS) {
                     mLeHandle = clientIf;
                     try {
-                        mBluetoothGatt.startMultiAdvertising(mLeHandle, mAdvertisement, mSettings);
+                        mBluetoothGatt.startMultiAdvertising(mLeHandle, mAdvertisement,
+                                mScanResponse, mSettings);
                     } catch (RemoteException e) {
                         Log.e(TAG, "fail to start le advertise: " + e);
                         mLeHandle = -1;
@@ -540,6 +543,19 @@
      */
     public void startAdvertising(Settings settings,
             AdvertisementData advertiseData, final AdvertiseCallback callback) {
+        startAdvertising(settings, advertiseData, null, callback);
+    }
+
+    /**
+     * Start Bluetooth LE Advertising.
+     * @param settings {@link Settings} for Bluetooth LE advertising.
+     * @param advertiseData {@link AdvertisementData} to be advertised in advertisement packet.
+     * @param scanResponse {@link AdvertisementData} for scan response.
+     * @param callback {@link AdvertiseCallback} for advertising status.
+     */
+    public void startAdvertising(Settings settings,
+            AdvertisementData advertiseData, AdvertisementData scanResponse,
+            final AdvertiseCallback callback) {
         if (callback == null) {
             throw new IllegalArgumentException("callback cannot be null");
         }
@@ -548,8 +564,7 @@
             return;
         }
         AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData,
-                settings,
-                mBluetoothGatt);
+                scanResponse, settings, mBluetoothGatt);
         UUID uuid = UUID.randomUUID();
         try {
             mBluetoothGatt.registerClient(new ParcelUuid(uuid), wrapper);
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 091b806..ceed52b 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -41,7 +41,9 @@
                               in BluetoothLeScanner.Settings settings,
                               in List<BluetoothLeScanFilter> filters);
     void stopScan(in int appIf, in boolean isServer);
-    void startMultiAdvertising(in int appIf, in BluetoothLeAdvertiseScanData.AdvertisementData data,
+    void startMultiAdvertising(in int appIf,
+                               in BluetoothLeAdvertiseScanData.AdvertisementData advertiseData,
+                               in BluetoothLeAdvertiseScanData.AdvertisementData scanResponse,
                                in BluetoothLeAdvertiser.Settings settings);
     void stopMultiAdvertising(in int appIf);
     void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c11b04c..9e02e4b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2352,11 +2352,11 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
-     * android.net.wifi.passpoint.PasspointManager} for handling management of
+     * android.net.wifi.passpoint.WifiPasspointManager} for handling management of
      * Wi-Fi passpoint access.
      *
      * @see #getSystemService
-     * @see android.net.wifi.passpoint.PasspointManager
+     * @see android.net.wifi.passpoint.WifiPasspointManager
      */
     public static final String WIFI_PASSPOINT_SERVICE = "wifipasspoint";
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0e2eab7..35bcc02 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1405,6 +1405,14 @@
     public static final String FEATURE_MANAGEDPROFILES = "android.software.managedprofiles";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device has a full implementation of the android.webkit.* APIs. Devices
+     * lacking this feature will not have a functioning WebView implementation.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_WEBVIEW = "android.software.webview";
+
+    /**
      * Action to external storage service to clean out removed apps.
      * @hide
      */
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 5674154..3f01dd2 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -64,7 +64,6 @@
  * List Resource</a>.</p>
  */
 public class ColorStateList implements Parcelable {
-
     private int[][] mStateSpecs; // must be parallel to mColors
     private int[] mColors;      // must be parallel to mStateSpecs
     private int mDefaultColor = 0xffff0000;
@@ -100,9 +99,9 @@
     public static ColorStateList valueOf(int color) {
         // TODO: should we collect these eventually?
         synchronized (sCache) {
-            WeakReference<ColorStateList> ref = sCache.get(color);
-            ColorStateList csl = ref != null ? ref.get() : null;
+            final WeakReference<ColorStateList> ref = sCache.get(color);
 
+            ColorStateList csl = ref != null ? ref.get() : null;
             if (csl != null) {
                 return csl;
             }
@@ -118,8 +117,7 @@
      */
     public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
             throws XmlPullParserException, IOException {
-
-        AttributeSet attrs = Xml.asAttributeSet(parser);
+        final AttributeSet attrs = Xml.asAttributeSet(parser);
 
         int type;
         while ((type=parser.next()) != XmlPullParser.START_TAG
@@ -133,22 +131,22 @@
         return createFromXmlInner(r, parser, attrs);
     }
 
-    /* Create from inside an XML document.  Called on a parser positioned at
-     * a tag in an XML document, tries to create a ColorStateList from that tag.
-     * Returns null if the tag is not a valid ColorStateList.
+    /**
+     * Create from inside an XML document. Called on a parser positioned at a
+     * tag in an XML document, tries to create a ColorStateList from that tag.
+     *
+     * @throws XmlPullParserException if the current tag is not &lt;selector>
+     * @return A color state list for the current tag.
      */
     private static ColorStateList createFromXmlInner(Resources r, XmlPullParser parser,
             AttributeSet attrs) throws XmlPullParserException, IOException {
-
-        ColorStateList colorStateList;
-
+        final ColorStateList colorStateList;
         final String name = parser.getName();
-
         if (name.equals("selector")) {
             colorStateList = new ColorStateList();
         } else {
             throw new XmlPullParserException(
-                parser.getPositionDescription() + ": invalid drawable tag " + name);
+                    parser.getPositionDescription() + ": invalid drawable tag " + name);
         }
 
         colorStateList.inflate(r, parser, attrs);
@@ -161,9 +159,8 @@
      * (0-255).
      */
     public ColorStateList withAlpha(int alpha) {
-        int[] colors = new int[mColors.length];
-
-        int len = colors.length;
+        final int[] colors = new int[mColors.length];
+        final int len = colors.length;
         for (int i = 0; i < len; i++) {
             colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
         }
@@ -176,7 +173,6 @@
      */
     private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
             throws XmlPullParserException, IOException {
-
         int type;
 
         final int innerDepth = parser.getDepth()+1;
@@ -259,10 +255,25 @@
         System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
     }
 
+    /**
+     * Indicates whether this color state list contains more than one state spec
+     * and will change color based on state.
+     *
+     * @return True if this color state list changes color based on state, false
+     *         otherwise.
+     * @see #getColorForState(int[], int)
+     */
     public boolean isStateful() {
         return mStateSpecs.length > 1;
     }
 
+    /**
+     * Indicates whether this color state list is opaque, which means that every
+     * color returned from {@link #getColorForState(int[], int)} has an alpha
+     * value of 255.
+     *
+     * @return True if this color state list is opaque.
+     */
     public boolean isOpaque() {
         final int n = mColors.length;
         for (int i = 0; i < n; i++) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 1692a79..a78f8e2 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -21,6 +21,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.Nullable;
 import android.content.pm.ActivityInfo;
 import android.graphics.Movie;
 import android.graphics.drawable.Drawable;
@@ -719,12 +720,12 @@
      * @param id The desired resource identifier, as generated by the aapt
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
-     * @param theme The theme used to style the drawable attributes.
+     * @param theme The theme used to style the drawable attributes, may be {@code null}.
      * @return Drawable An object that can be used to draw this resource.
      * @throws NotFoundException Throws NotFoundException if the given ID does
      *         not exist.
      */
-    public Drawable getDrawable(int id, Theme theme) throws NotFoundException {
+    public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
         TypedValue value;
         synchronized (mAccessLock) {
             value = mTmpValue;
@@ -777,12 +778,12 @@
      *            The value 0 is an invalid identifier.
      * @param density The desired screen density indicated by the resource as
      *            found in {@link DisplayMetrics}.
-     * @param theme The theme used to style the drawable attributes.
+     * @param theme The theme used to style the drawable attributes, may be {@code null}.
      * @return Drawable An object that can be used to draw this resource.
      * @throws NotFoundException Throws NotFoundException if the given ID does
      *             not exist.
      */
-    public Drawable getDrawableForDensity(int id, int density, Theme theme) {
+    public Drawable getDrawableForDensity(int id, int density, @Nullable Theme theme) {
         TypedValue value;
         synchronized (mAccessLock) {
             value = mTmpValue;
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
index 92d6f75..da5c128 100644
--- a/core/java/android/hardware/usb/UsbConfiguration.java
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
@@ -44,13 +44,13 @@
      * Mask for "self-powered" bit in the configuration's attributes.
      * @see #getAttributes
      */
-    public static final int ATTR_SELF_POWERED_MASK = 1 << 6;
+    private static final int ATTR_SELF_POWERED = 1 << 6;
 
     /**
      * Mask for "remote wakeup" bit in the configuration's attributes.
      * @see #getAttributes
      */
-    public static final int ATTR_REMOTE_WAKEUP_MASK = 1 << 5;
+    private static final int ATTR_REMOTE_WAKEUP = 1 << 5;
 
     /**
      * UsbConfiguration should only be instantiated by UsbService implementation
@@ -83,19 +83,23 @@
     }
 
     /**
-     * Returns the configuration's attributes field.
-     * This field contains a bit field with the following flags:
+     * Returns the self-powered attribute value configuration's attributes field.
+     * This attribute indicates that the device has a power source other than the USB connection.
      *
-     * Bit 7: always set to 1
-     * Bit 6: self-powered
-     * Bit 5: remote wakeup enabled
-     * Bit 0-4: reserved
-     * @see #ATTR_SELF_POWERED_MASK
-     * @see #ATTR_REMOTE_WAKEUP_MASK
-     * @return the configuration's attributes
+     * @return the configuration's self-powered attribute
      */
-    public int getAttributes() {
-        return mAttributes;
+    public boolean isSelfPowered() {
+        return (mAttributes & ATTR_SELF_POWERED) != 0;
+    }
+
+    /**
+     * Returns the remote-wakeup attribute value configuration's attributes field.
+     * This attributes that the device may signal the host to wake from suspend.
+     *
+     * @return the configuration's remote-wakeup attribute
+     */
+    public boolean isRemoteWakeup() {
+        return (mAttributes & ATTR_REMOTE_WAKEUP) != 0;
     }
 
     /**
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 6283951..c062b3a 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -104,7 +104,7 @@
      * Sets the current {@link android.hardware.usb.UsbInterface}.
      * Used to select between two interfaces with the same ID but different alternate setting.
      *
-     * @return true if the interface was successfully released
+     * @return true if the interface was successfully selected
      */
     public boolean setInterface(UsbInterface intf) {
         return native_set_interface(intf.getId(), intf.getAlternateSetting());
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1837335..80a9598 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1655,9 +1655,16 @@
     }
 
     /** {@hide} */
-    public void registerNetworkFactory(Messenger messenger) {
+    public void registerNetworkFactory(Messenger messenger, String name) {
         try {
-            mService.registerNetworkFactory(messenger);
+            mService.registerNetworkFactory(messenger, name);
+        } catch (RemoteException e) { }
+    }
+
+    /** {@hide} */
+    public void unregisterNetworkFactory(Messenger messenger) {
+        try {
+            mService.unregisterNetworkFactory(messenger);
         } catch (RemoteException e) { }
     }
 
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 885b8b6..d97b1e9 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -153,7 +153,9 @@
 
     void setAirplaneMode(boolean enable);
 
-    void registerNetworkFactory(in Messenger messenger);
+    void registerNetworkFactory(in Messenger messenger, in String name);
+
+    void unregisterNetworkFactory(in Messenger messenger);
 
     void registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
             in NetworkCapabilities nc, int score);
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
new file mode 100644
index 0000000..4730bab
--- /dev/null
+++ b/core/java/android/net/IpConfiguration.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.LinkProperties;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A class representing a configured network.
+ * @hide
+ */
+public class IpConfiguration implements Parcelable {
+    private static final String TAG = "IpConfiguration";
+
+    public enum IpAssignment {
+        /* Use statically configured IP settings. Configuration can be accessed
+         * with linkProperties */
+        STATIC,
+        /* Use dynamically configured IP settigns */
+        DHCP,
+        /* no IP details are assigned, this is used to indicate
+         * that any existing IP settings should be retained */
+        UNASSIGNED
+    }
+
+    public IpAssignment ipAssignment;
+
+    public enum ProxySettings {
+        /* No proxy is to be used. Any existing proxy settings
+         * should be cleared. */
+        NONE,
+        /* Use statically configured proxy. Configuration can be accessed
+         * with linkProperties */
+        STATIC,
+        /* no proxy details are assigned, this is used to indicate
+         * that any existing proxy settings should be retained */
+        UNASSIGNED,
+        /* Use a Pac based proxy.
+         */
+        PAC
+    }
+
+    public ProxySettings proxySettings;
+
+    public LinkProperties linkProperties;
+
+    public IpConfiguration(IpConfiguration source) {
+        if (source != null) {
+            ipAssignment = source.ipAssignment;
+            proxySettings = source.proxySettings;
+            linkProperties = new LinkProperties(source.linkProperties);
+        } else {
+            ipAssignment = IpAssignment.UNASSIGNED;
+            proxySettings = ProxySettings.UNASSIGNED;
+            linkProperties = new LinkProperties();
+        }
+    }
+
+    public IpConfiguration() {
+         this(null);
+    }
+
+    public IpConfiguration(IpAssignment ipAssignment,
+                           ProxySettings proxySettings,
+                           LinkProperties linkProperties) {
+        this.ipAssignment = ipAssignment;
+        this.proxySettings = proxySettings;
+        this.linkProperties = new LinkProperties(linkProperties);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sbuf = new StringBuilder();
+        sbuf.append("IP assignment: " + ipAssignment.toString());
+        sbuf.append("\n");
+        sbuf.append("Proxy settings: " + proxySettings.toString());
+        sbuf.append("\n");
+        sbuf.append(linkProperties.toString());
+        sbuf.append("\n");
+
+        return sbuf.toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+
+        if (!(o instanceof IpConfiguration)) {
+            return false;
+        }
+
+        IpConfiguration other = (IpConfiguration) o;
+        return this.ipAssignment == other.ipAssignment &&
+                this.proxySettings == other.proxySettings &&
+                Objects.equals(this.linkProperties, other.linkProperties);
+    }
+
+    @Override
+    public int hashCode() {
+        return 13 + (linkProperties != null ? linkProperties.hashCode() : 0) +
+               17 * ipAssignment.ordinal() +
+               47 * proxySettings.ordinal();
+    }
+
+    /** Implement the Parcelable interface */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface  */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(ipAssignment.name());
+        dest.writeString(proxySettings.name());
+        dest.writeParcelable(linkProperties, flags);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<IpConfiguration> CREATOR =
+        new Creator<IpConfiguration>() {
+            public IpConfiguration createFromParcel(Parcel in) {
+                IpConfiguration config = new IpConfiguration();
+                config.ipAssignment = IpAssignment.valueOf(in.readString());
+                config.proxySettings = ProxySettings.valueOf(in.readString());
+                config.linkProperties = in.readParcelable(null);
+                return config;
+            }
+
+            public IpConfiguration[] newArray(int size) {
+                return new IpConfiguration[size];
+            }
+        };
+}
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 635a50f..9218c11 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -25,7 +25,6 @@
 import android.nfc.INfcAdapterExtras;
 import android.nfc.INfcTag;
 import android.nfc.INfcCardEmulation;
-import android.nfc.INfcUnlockSettings;
 import android.os.Bundle;
 
 /**
@@ -36,7 +35,6 @@
     INfcTag getNfcTagInterface();
     INfcCardEmulation getNfcCardEmulationInterface();
     INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);
-    INfcUnlockSettings getNfcUnlockSettingsInterface();
 
     int getState();
     boolean disable(boolean saveState);
diff --git a/core/java/android/nfc/INfcUnlockSettings.aidl b/core/java/android/nfc/INfcUnlockSettings.aidl
deleted file mode 100644
index 649eeed..0000000
--- a/core/java/android/nfc/INfcUnlockSettings.aidl
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.nfc;
-
-import android.nfc.Tag;
-import java.util.List;
-
-/**
- * Interface to NFC unlock functionality.
- *
- * @hide
- */
-interface INfcUnlockSettings {
-
-    /**
-     * Checks the validity of the tag and attempts to unlock the screen.
-     *
-     * @return true if the screen was successfuly unlocked.
-     */
-    boolean tryUnlock(int userId, in Tag tag);
-
-    /**
-     * Registers the given tag as an unlock tag. Subsequent calls to {@code tryUnlock}
-     * with the same {@code tag} should succeed.
-     *
-     * @return true if the tag was successfully registered.
-     */
-    boolean registerTag(int userId, in Tag tag);
-
-    /**
-     * Deregisters the tag with the corresponding timestamp.
-     * Subsequent calls to {@code tryUnlock} with the same tag should fail.
-     *
-     * @return true if the tag was successfully deleted.
-     */
-    boolean deregisterTag(int userId, long timestamp);
-
-    /**
-     * Used for user-visible rendering of registered tags.
-     *
-     * @return a list of the times in millis since epoch when the registered tags were paired.
-     */
-    long[] getTagRegistryTimes(int userId);
-
-    /**
-     * Determines the state of the NFC unlock feature.
-     *
-     * @return true if NFC unlock is enabled.
-     */
-    boolean getNfcUnlockEnabled(int userId);
-
-    /**
-     * Sets the state [ON | OFF] of the NFC unlock feature.
-     */
-    void setNfcUnlockEnabled(int userId, boolean enabled);
-}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 96a3947..dd8e41c 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -292,7 +292,6 @@
     static INfcAdapter sService;
     static INfcTag sTagService;
     static INfcCardEmulation sCardEmulationService;
-    static INfcUnlockSettings sNfcUnlockSettingsService;
 
     /**
      * The NfcAdapter object for each application context.
@@ -433,13 +432,6 @@
                 throw new UnsupportedOperationException();
             }
 
-            try {
-               sNfcUnlockSettingsService = sService.getNfcUnlockSettingsInterface();
-            } catch (RemoteException e) {
-                Log.e(TAG, "could not retrieve NFC unlock settings service");
-                sNfcUnlockSettingsService = null;
-            }
-
             sIsInitialized = true;
         }
         if (context == null) {
@@ -557,22 +549,6 @@
     }
 
     /**
-     * Returns the binder interface to the NFC unlock service.
-     *
-     * @throws UnsupportedOperationException if the service is not available.
-     * @hide
-     */
-    public INfcUnlockSettings getNfcUnlockSettingsService() throws UnsupportedOperationException {
-         isEnabled();
-
-        if (sNfcUnlockSettingsService == null) {
-            throw new UnsupportedOperationException("NfcUnlockSettingsService not available");
-        }
-
-        return sNfcUnlockSettingsService;
-    }
-
-    /**
      * NFC service dead - attempt best effort recovery
      * @hide
      */
diff --git a/core/java/android/nfc/NfcUnlock.java b/core/java/android/nfc/NfcUnlock.java
deleted file mode 100644
index 82dcd96..0000000
--- a/core/java/android/nfc/NfcUnlock.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.nfc;
-
-import static com.android.internal.util.Preconditions.checkNotNull;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.util.HashMap;
-
-/**
- * Provides an interface to read and update NFC unlock settings.
- * <p/>
- * Allows system services (currently exclusively LockSettingsService) to
- * register NFC tags to be used to unlock the device, as well as the ability
- * to enable/disable the service entirely.
- *
- */
-public class NfcUnlock {
-
-    /**
-     * Action to unlock the device.
-     *
-     * @hide
-     */
-    public static final String ACTION_NFC_UNLOCK = "android.nfc.ACTION_NFC_UNLOCK";
-    /**
-     * Permission to unlock the device.
-     *
-     * @hide
-     */
-    public static final String NFC_UNLOCK_PERMISSION = "android.permission.NFC_UNLOCK";
-
-    /**
-     * Property to enable NFC Unlock
-     *
-     * @hide
-     */
-    public static final String PROPERTY = "ro.com.android.nfc.unlock";
-
-    private static final String TAG = "NfcUnlock";
-    private static HashMap<Context, NfcUnlock> sNfcUnlocks = new HashMap<Context, NfcUnlock>();
-
-    private final Context mContext;
-    private final boolean mEnabled;
-    private INfcUnlockSettings sService;
-
-    private NfcUnlock(Context context, INfcUnlockSettings service) {
-        this.mContext = checkNotNull(context);
-        this.sService = checkNotNull(service);
-        this.mEnabled = getPropertyEnabled();
-    }
-
-    /**
-     * Returns an instance of {@link NfcUnlock}.
-     */
-    public static synchronized NfcUnlock getInstance(NfcAdapter nfcAdapter) {
-        Context context = nfcAdapter.getContext();
-        if (context == null) {
-            Log.e(TAG, "NfcAdapter context is null");
-            throw new UnsupportedOperationException();
-        }
-
-        NfcUnlock manager = sNfcUnlocks.get(context);
-        if (manager == null) {
-            INfcUnlockSettings service = nfcAdapter.getNfcUnlockSettingsService();
-            manager = new NfcUnlock(context, service);
-            sNfcUnlocks.put(context, manager);
-        }
-
-        return manager;
-    }
-
-    /**
-     * Registers the given {@code tag} as an unlock tag.
-     *
-     * @return true if the tag was successfully registered.
-     * @hide
-     */
-    public boolean registerTag(Tag tag) {
-        enforcePropertyEnabled();
-
-        int currentUser = ActivityManager.getCurrentUser();
-
-        try {
-            return sService.registerTag(currentUser, tag);
-        } catch (RemoteException e) {
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
-                return false;
-            }
-
-            try {
-                return sService.registerTag(currentUser, tag);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Deregisters the given {@code tag} as an unlock tag.
-     *
-     * @return true if the tag was successfully deregistered.
-     * @hide
-     */
-    public boolean deregisterTag(long timestamp) {
-        enforcePropertyEnabled();
-        int currentUser = ActivityManager.getCurrentUser();
-
-        try {
-            return sService.deregisterTag(currentUser, timestamp);
-        } catch (RemoteException e) {
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
-                return false;
-            }
-
-            try {
-                return sService.deregisterTag(currentUser, timestamp);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Determines the enable state of the NFC unlock feature.
-     *
-     * @return true if NFC unlock is enabled.
-     */
-    public boolean getNfcUnlockEnabled() {
-        enforcePropertyEnabled();
-        int currentUser = ActivityManager.getCurrentUser();
-
-        try {
-            return sService.getNfcUnlockEnabled(currentUser);
-        } catch (RemoteException e) {
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
-                return false;
-            }
-
-            try {
-                return sService.getNfcUnlockEnabled(currentUser);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Set the enable state of the NFC unlock feature.
-     *
-     * @return true if the setting was successfully persisted.
-     * @hide
-     */
-    public boolean setNfcUnlockEnabled(boolean enabled) {
-        enforcePropertyEnabled();
-        int currentUser = ActivityManager.getCurrentUser();
-
-        try {
-            sService.setNfcUnlockEnabled(currentUser, enabled);
-            return true;
-        }  catch (RemoteException e) {
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
-                return false;
-            }
-
-            try {
-                sService.setNfcUnlockEnabled(currentUser, enabled);
-                return true;
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
-                return false;
-            }
-
-        }
-    }
-
-    /**
-     * Returns a list of times (in millis since epoch) corresponding to when
-     * unlock tags were registered.
-     *
-     * @hide
-     */
-    @Nullable
-    public long[] getTagRegistryTimes() {
-        enforcePropertyEnabled();
-        int currentUser = ActivityManager.getCurrentUser();
-
-        try {
-            return sService.getTagRegistryTimes(currentUser);
-        } catch (RemoteException e) {
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover NfcUnlockSettingsService");
-                return null;
-            }
-
-            try {
-                return sService.getTagRegistryTimes(currentUser);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach NfcUnlockSettingsService", ee);
-                return null;
-            }
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public static boolean getPropertyEnabled() {
-        return SystemProperties.get(PROPERTY).equals("ON");
-    }
-
-    private void recoverService() {
-        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
-        sService = adapter.getNfcUnlockSettingsService();
-    }
-
-
-    private void enforcePropertyEnabled() {
-        if (!mEnabled) {
-            throw new UnsupportedOperationException("NFC Unlock property is not enabled");
-        }
-    }
-}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 6c7b08d..61194e9 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -38,7 +38,7 @@
 
     void userActivity(long time, int event, int flags);
     void wakeUp(long time);
-    void goToSleep(long time, int reason);
+    void goToSleep(long time, int reason, int flags);
     void nap(long time);
     boolean isInteractive();
 
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 5b2c8db..d5177e8 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -321,6 +321,12 @@
      */
     public static final String REBOOT_RECOVERY = "recovery";
     
+    /**
+     * Go to sleep flag: Skip dozing state and directly go to full sleep.
+     * @hide
+     */
+    public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0;
+
     final Context mContext;
     final IPowerManager mService;
     final Handler mHandler;
@@ -500,8 +506,15 @@
      * @see #wakeUp
      */
     public void goToSleep(long time) {
+        goToSleep(time, GO_TO_SLEEP_REASON_USER, 0);
+    }
+
+    /**
+     * @hide
+     */
+    public void goToSleep(long time, int reason, int flags) {
         try {
-            mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);
+            mService.goToSleep(time, reason, flags);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 312cdbe..ee219e3 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -266,6 +266,17 @@
      */
     public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
 
+    /**
+     * Key for user restrictions. Specifies that the user is not allowed to send or receive
+     * phone calls or text messages. Emergency calls may still be permitted.
+     * The default value is <code>false</code>.
+     * <p/>
+     * Type: Boolean
+     * @see #setUserRestrictions(Bundle)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_TELEPHONY = "no_telephony";
+
     /** @hide */
     public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
     /** @hide */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2d03e1d..e9ffc52 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3477,11 +3477,6 @@
         public static final String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
 
         /**
-         * Whether the NFC unlock feature is enabled (0 = false, 1 = true)
-         */
-        public static final String NFC_UNLOCK_ENABLED = "nfc_unlock_enabled";
-
-        /**
          * Whether lock pattern will vibrate as user enters (0 = false, 1 =
          * true)
          *
diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/service/fingerprint/FingerprintManager.java
index 0d14c59..2fcec52 100644
--- a/core/java/android/service/fingerprint/FingerprintManager.java
+++ b/core/java/android/service/fingerprint/FingerprintManager.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManagerNative;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
@@ -25,6 +26,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Log;
 
 /**
@@ -33,7 +35,7 @@
 
 public class FingerprintManager {
     private static final String TAG = "FingerprintManager";
-    protected static final boolean DEBUG = true;
+    private static final boolean DEBUG = true;
     private static final String FINGERPRINT_SERVICE_PACKAGE = "com.android.service.fingerprint";
     private static final String FINGERPRINT_SERVICE_CLASS =
             "com.android.service.fingerprint.FingerprintService";
@@ -58,6 +60,7 @@
 
     private IFingerprintService mService;
     private FingerprintManagerReceiver mClientReceiver;
+    private Context mContext;
 
     private Handler mHandler = new Handler() {
         public void handleMessage(android.os.Message msg) {
@@ -80,6 +83,7 @@
     };
 
     public FingerprintManager(Context context) {
+        mContext = context;
         // Connect to service...
         Intent intent = new Intent();
         intent.setClassName(FINGERPRINT_SERVICE_PACKAGE, FINGERPRINT_SERVICE_CLASS);
@@ -129,6 +133,17 @@
     };
 
     /**
+     * Determine whether the user has at least one fingerprint enrolled and enabled.
+     *
+     * @return true if at least one is enrolled and enabled
+     */
+    public boolean enrolledAndEnabled() {
+        ContentResolver res = mContext.getContentResolver();
+        return Settings.Secure.getInt(res, "fingerprint_enabled", 0) != 0
+                && FingerprintUtils.getFingerprintIdsForUser(res, getCurrentUserId()).length > 0;
+    }
+
+    /**
      * Start the enrollment process.  Timeout dictates how long to wait for the user to
      * enroll a fingerprint.
      *
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 0bd46bc..b17f502 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -115,7 +115,7 @@
             if (count > 0 && selStart == selEnd && selStart > 0) {
                 char c = content.charAt(selStart - 1);
 
-                if (c == i || c == Character.toUpperCase(i) && view != null) {
+                if ((c == i || c == Character.toUpperCase(i)) && view != null) {
                     if (showCharacterPicker(view, content, c, false, count)) {
                         resetMetaState(content);
                         return true;
diff --git a/core/java/android/tv/TvInputManager.java b/core/java/android/tv/TvInputManager.java
index c5f179a..dfa84f8 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/core/java/android/tv/TvInputManager.java
@@ -414,8 +414,9 @@
          *
          * @param surface A {@link android.view.Surface} used to render video.
          * @throws IllegalStateException if the session has been already released.
+         * @hide
          */
-        void setSurface(Surface surface) {
+        public void setSurface(Surface surface) {
             if (mToken == null) {
                 throw new IllegalStateException("the session has been already released");
             }
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index b2839cb..cf125bc 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -366,10 +366,8 @@
      * Deep copies the data into native to simplify reference ownership.
      */
     public void setOutline(Outline outline) {
-        if (outline == null) {
+        if (outline == null || outline.isEmpty()) {
             nSetOutlineEmpty(mNativeRenderNode);
-        } else if (!outline.isValid()) {
-            throw new IllegalArgumentException("Outline must be valid");
         } else if (outline.mRect != null) {
             nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
                     outline.mRect.right, outline.mRect.bottom, outline.mRadius);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6dc7286..0f21c1d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10680,24 +10680,30 @@
     }
 
     /**
-     * Sets the outline of the view, which defines the shape of the shadow it
-     * casts.
+     * Sets the {@link Outline} of the view, which defines the shape of the shadow it
+     * casts, and enables outline clipping.
      * <p>
-     * If the outline is not set or is null, shadows will be cast from the
+     * By default, a View queries its Outline from its background drawable, via
+     * {@link Drawable#getOutline(Outline)}. Manually setting the Outline with this method allows
+     * this behavior to be overridden.
+     * <p>
+     * If the outline is empty or is null, shadows will be cast from the
      * bounds of the View.
+     * <p>
+     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
      *
      * @param outline The new outline of the view.
-     *         Must be {@link android.graphics.Outline#isValid() valid.}
+     *
+     * @see #setClipToOutline(boolean)
+     * @see #getClipToOutline()
      */
     public void setOutline(@Nullable Outline outline) {
-        if (outline != null && !outline.isValid()) {
-            throw new IllegalArgumentException("Outline must not be invalid");
-        }
-
         mPrivateFlags3 |= PFLAG3_OUTLINE_DEFINED;
 
-        if (outline == null) {
-            mOutline = null;
+        if (outline == null || outline.isEmpty()) {
+            if (mOutline != null) {
+                mOutline.setEmpty();
+            }
         } else {
             // always copy the path since caller may reuse
             if (mOutline == null) {
@@ -10708,12 +10714,30 @@
         mRenderNode.setOutline(mOutline);
     }
 
+    /**
+     * Returns whether the Outline should be used to clip the contents of the View.
+     * <p>
+     * Note that this flag will only be respected if the View's Outline returns true from
+     * {@link Outline#canClip()}.
+     *
+     * @see #setOutline(Outline)
+     * @see #setClipToOutline(boolean)
+     */
     public final boolean getClipToOutline() {
         return mRenderNode.getClipToOutline();
     }
 
+    /**
+     * Sets whether the View's Outline should be used to clip the contents of the View.
+     * <p>
+     * Note that this flag will only be respected if the View's Outline returns true from
+     * {@link Outline#canClip()}.
+     *
+     * @see #setOutline(Outline)
+     * @see #getClipToOutline()
+     */
     public void setClipToOutline(boolean clipToOutline) {
-        // TODO: add a fast invalidation here
+        damageInParent();
         if (getClipToOutline() != clipToOutline) {
             mRenderNode.setClipToOutline(clipToOutline);
         }
@@ -10726,10 +10750,10 @@
                 mOutline = new Outline();
             } else {
                 //invalidate outline, to ensure background calculates it
-                mOutline.reset();
+                mOutline.setEmpty();
             }
             if (mBackground.getOutline(mOutline)) {
-                if (!mOutline.isValid()) {
+                if (mOutline.isEmpty()) {
                     throw new IllegalStateException("Background drawable failed to build outline");
                 }
                 mRenderNode.setOutline(mOutline);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 34967df..d5f0834 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -995,13 +995,12 @@
     public void addAction(int action) {
         enforceNotSealed();
 
-        AccessibilityAction newAction = getActionSingleton(action);
-        if (newAction == null) {
-            // This means it is not one of the standard actions
-            throw new IllegalArgumentException("Argument is not one of the standard actions");
+        if ((action & ACTION_TYPE_MASK) != 0) {
+            throw new IllegalArgumentException("Action is not a combination of the standard " +
+                    "actions: " + action);
         }
 
-        addAction(newAction);
+        addLegacyStandardActions(action);
     }
 
     /**
diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index 01eaec4..a3c7b0a 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -100,18 +100,19 @@
     }
     request->buffer_length = length;
 
+    // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
+    request->client_data = (void *)env->NewGlobalRef(thiz);
+
     if (usb_request_queue(request)) {
         if (request->buffer) {
             // free our buffer if usb_request_queue fails
             free(request->buffer);
             request->buffer = NULL;
         }
+        env->DeleteGlobalRef((jobject)request->client_data);
         return false;
-    } else {
-        // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
-        request->client_data = (void *)env->NewGlobalRef(thiz);
-        return true;
     }
+    return true;
 }
 
 static jint
@@ -152,16 +153,17 @@
     }
     request->buffer_length = length;
 
+    // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
+    // we also need this to make sure our native buffer is not deallocated
+    // while IO is active
+    request->client_data = (void *)env->NewGlobalRef(thiz);
+
     if (usb_request_queue(request)) {
         request->buffer = NULL;
+        env->DeleteGlobalRef((jobject)request->client_data);
         return false;
-    } else {
-        // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
-        // we also need this to make sure our native buffer is not deallocated
-        // while IO is active
-        request->client_data = (void *)env->NewGlobalRef(thiz);
-        return true;
     }
+    return true;
 }
 
 static jint
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a97d5fc..7b200c4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -833,15 +833,8 @@
     <!-- Allows access to the loop radio (Android@Home mesh network) device.
 	@hide -->
     <permission android:name="android.permission.LOOP_RADIO"
-	    android:permissionGroup="android.permission-group.NETWORK"
-	    android:protectionLevel="signature|system" />
-
-    <!-- Allows for the NFC process to unlock the device
-         @hide This should only be used by the Nfc apk
-    -->
-    <permission android:name="android.permission.NFC_UNLOCK"
-        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="signature" />
+	android:permissionGroup="android.permission-group.NETWORK"
+	android:protectionLevel="signature|system" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 463dda2..5375c14 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -498,6 +498,14 @@
     -->
     <integer name="config_longPressOnPowerBehavior">1</integer>
 
+    <!-- Control the behavior when the user short presses the power button.
+            0 - Nothing
+            1 - Go to sleep (doze)
+            2 - Really go to sleep (don't doze)
+            3 - Really go to sleep and go home (don't doze)
+    -->
+    <integer name="config_shortPressOnPowerBehavior">1</integer>
+
     <!-- Package name for default keyguard appwidget [DO NOT TRANSLATE] -->
     <string name="widget_default_package_name"></string>
 
@@ -1215,6 +1223,49 @@
     -->
     <bool name="config_powerDecoupleInteractiveModeFromDisplay">false</bool>
 
+    <!-- User activity timeout: Minimum screen off timeout in milliseconds.
+
+         Sets a lower bound for the {@link Settings.System#SCREEN_OFF_TIMEOUT} setting
+         which determines how soon the device will go to sleep when there is no
+         user activity.
+
+         This value must be greater than zero, otherwise the device will immediately
+         fall asleep again as soon as it is awoken.
+    -->
+    <integer name="config_minimumScreenOffTimeout">10000</integer>
+
+    <!-- User activity timeout: Maximum screen dim duration in milliseconds.
+
+         Sets an upper bound for how long the screen will dim before the device goes
+         to sleep when there is no user activity.  The dim duration is subtracted from
+         the overall screen off timeout to determine the screen dim timeout.
+         When the screen dim timeout expires, the screen will dim, shortly thereafter
+         the device will go to sleep.
+
+         If the screen off timeout is very short, the dim duration may be reduced
+         proportionally.  See config_maximumScreenDimRatio.
+
+         This value may be zero in which case the screen will not dim before the
+         device goes to sleep.
+    -->
+    <integer name="config_maximumScreenDimDuration">7000</integer>
+
+    <!-- User activity timeout: Maximum screen dim duration as a percentage of screen off timeout.
+
+         This resource is similar to config_maximumScreenDimDuration but the maximum
+         screen dim duration is defined as a ratio of the overall screen off timeout
+         instead of as an absolute value in milliseconds.  This is useful for reducing
+         the dim duration when the screen off timeout is very short.
+
+         When computing the screen dim duration, the power manager uses the lesser
+         of the effective durations expressed by config_maximumScreenDimDuration and
+         config_maximumScreenDimRatio.
+
+         This value must be between 0% and 100%.  If the value is zero, the screen will not
+         dim before the device goes to sleep.
+    -->
+    <fraction name="config_maximumScreenDimRatio">20%</fraction>
+
     <!-- Base "touch slop" value used by ViewConfiguration as a
          movement threshold where scrolling should begin. -->
     <dimen name="config_viewConfigurationTouchSlop">8dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2d60b86..d7a5573 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -305,6 +305,7 @@
   <java-symbol type="integer" name="config_ntpRetry" />
   <java-symbol type="integer" name="config_ntpThreshold" />
   <java-symbol type="integer" name="config_ntpTimeout" />
+  <java-symbol type="integer" name="config_shortPressOnPowerBehavior" />
   <java-symbol type="integer" name="config_toastDefaultGravity" />
   <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
   <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
@@ -1639,6 +1640,9 @@
   <java-symbol type="string" name="enable_explore_by_touch_warning_message" />
   <java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" />
   <java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" />
+  <java-symbol type="integer" name="config_minimumScreenOffTimeout" />
+  <java-symbol type="integer" name="config_maximumScreenDimDuration" />
+  <java-symbol type="fraction" name="config_maximumScreenDimRatio" />
   <java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" />
   <java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
 
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index cad030a..db125e6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -23,15 +23,15 @@
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
 
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.AuthAlgorithm;
-import android.net.wifi.WifiConfiguration.IpAssignment;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.ProxySettings;
-import android.net.wifi.WifiEnterpriseConfig;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.RouteInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiEnterpriseConfig;
 
 import java.io.InputStream;
 import java.net.InetAddress;
@@ -174,12 +174,12 @@
         public void endElement(String uri, String localName, String tagName) throws SAXException {
             if (tagName.equalsIgnoreCase("accesspoint")) {
                 if (mLinkProperties != null) {
-                    config.ipAssignment = IpAssignment.STATIC;
-                    config.linkProperties = mLinkProperties;
+                    config.setIpAssignment(IpAssignment.STATIC);
+                    config.setLinkProperties(mLinkProperties);
                 } else {
-                    config.ipAssignment = IpAssignment.DHCP;
+                    config.setIpAssignment(IpAssignment.DHCP);
                 }
-                config.proxySettings = ProxySettings.NONE;
+                config.setProxySettings(ProxySettings.NONE);
                 networks.add(config);
                 mLinkProperties = null;
             }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 91c3093..08618d6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -18,12 +18,12 @@
 
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
 import android.net.NetworkInfo.State;
 import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.IpAssignment;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.ProxySettings;
+import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.Environment;
 import android.os.PowerManager;
@@ -233,8 +233,8 @@
         } else {
             config.preSharedKey = '"' + mPassword + '"';
         }
-        config.ipAssignment = IpAssignment.DHCP;
-        config.proxySettings = ProxySettings.NONE;
+        config.setIpAssignment(IpAssignment.DHCP);
+        config.setProxySettings(ProxySettings.NONE);
 
         assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
                 connectToWifiWithConfiguration(config));
diff --git a/docs/html/distribute/essentials/gpfe-guidelines.jd b/docs/html/distribute/essentials/gpfe-guidelines.jd
index 8b47671..799009f 100644
--- a/docs/html/distribute/essentials/gpfe-guidelines.jd
+++ b/docs/html/distribute/essentials/gpfe-guidelines.jd
@@ -115,10 +115,6 @@
   <hr>
 </div>
 
-<div class="figure">
-  <img src="{@docRoot}images/gp-edu-monetize.png">
-</div>
-
 <p>
   In-app purchase is currently not supported with Google Play for Education, so
   a student device will block any transactions. To avoid confusion, be sure to
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index c6ba75c..d87c3cb 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -23,9 +23,9 @@
 
 /**
  * Defines a simple shape, used for bounding graphical regions.
- *
+ * <p>
  * Can be used with a View, or computed by a Drawable, to drive the shape of shadows cast by a
- * View.
+ * View, or to clip the contents of the View.
  *
  * @see View#setOutline(Outline)
  * @see Drawable#getOutline(Outline)
@@ -41,7 +41,7 @@
     public Path mPath;
 
     /**
-     * Constructs an invalid Outline. Call one of the setter methods to make
+     * Constructs an empty Outline. Call one of the setter methods to make
      * the outline valid for use with a View.
      */
     public Outline() {}
@@ -49,23 +49,31 @@
     /**
      * Constructs an Outline with a copy of the data in src.
      */
-    public Outline(@Nullable Outline src) {
+    public Outline(@NonNull Outline src) {
         set(src);
     }
 
-    public void reset() {
+    /**
+     * Sets the outline to be empty.
+     *
+     * @see #isEmpty()
+     */
+    public void setEmpty() {
         mRadius = 0;
         mRect = null;
         mPath = null;
     }
 
     /**
-     * Returns whether the Outline is valid for use with a View.
+     * Returns whether the Outline is empty.
      * <p>
-     * Outlines are invalid when constructed until a setter method is called.
+     * Outlines are empty when constructed, or if {@link #setEmpty()} is called,
+     * until a setter method is called
+     *
+     * @see #setEmpty()
      */
-    public boolean isValid() {
-        return mRect != null || mPath != null;
+    public boolean isEmpty() {
+        return mRect == null && mPath == null;
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 3eabc3a..3ef1d68 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.annotation.NonNull;
 import android.graphics.Insets;
 import android.graphics.Xfermode;
 import android.os.Trace;
@@ -512,13 +513,12 @@
     }
 
     /**
-     * Indicates whether this view will change its appearance based on state.
-     * Clients can use this to determine whether it is necessary to calculate
-     * their state and call setState.
+     * Indicates whether this drawable will change its appearance based on
+     * state. Clients can use this to determine whether it is necessary to
+     * calculate their state and call setState.
      *
-     * @return True if this view changes its appearance based on state, false
-     *         otherwise.
-     *
+     * @return True if this drawable changes its appearance based on state,
+     *         false otherwise.
      * @see #setState(int[])
      */
     public boolean isStateful() {
@@ -817,11 +817,12 @@
     /**
      * Return in padding the insets suggested by this Drawable for placing
      * content inside the drawable's bounds. Positive values move toward the
-     * center of the Drawable (set Rect.inset). Returns true if this drawable
-     * actually has a padding, else false. When false is returned, the padding
-     * is always set to 0.
+     * center of the Drawable (set Rect.inset).
+     *
+     * @return true if this drawable actually has a padding, else false. When false is returned,
+     * the padding is always set to 0.
      */
-    public boolean getPadding(Rect padding) {
+    public boolean getPadding(@NonNull Rect padding) {
         padding.set(0, 0, 0, 0);
         return false;
     }
@@ -842,13 +843,16 @@
      * This method will be called by a View on its background Drawable after bounds change, or its
      * Drawable is invalidated, if the View's Outline isn't set explicitly. This allows the
      * background Drawable to define the shape of the shadow cast by the View.
-     *
+     * <p>
      * The default behavior defines the outline to be the bounding rectangle. Subclasses that wish
      * to convey a different shape must override this method.
      *
+     * @return true if this drawable actually has an outline, else false. The outline must be
+     *         populated by the drawable if true is returned.
+     *
      * @see View#setOutline(android.graphics.Outline)
      */
-    public boolean getOutline(Outline outline) {
+    public boolean getOutline(@NonNull Outline outline) {
         outline.setRect(getBounds());
         return true;
     }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3a3f76d..575667d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2557,60 +2557,191 @@
     // class is not used by other parts of the framework, which instead use definitions and methods
     // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService.
 
-    /** {@hide} The audio output device code for the small speaker at the front of the device used
+    /** @hide
+     *  The audio output device code for the small speaker at the front of the device used
      *  when placing calls.  Does not refer to an in-ear headphone without attached microphone,
      *  such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a
      *  {@link #DEVICE_OUT_WIRED_HEADPHONE}.
      */
     public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE;
-    /** {@hide} The audio output device code for the built-in speaker */
+    /** @hide
+     *  The audio output device code for the built-in speaker */
     public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER;
-    /** {@hide} The audio output device code for a wired headset with attached microphone */
+    /** @hide
+     * The audio output device code for a wired headset with attached microphone */
     public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
-    /** {@hide} The audio output device code for a wired headphone without attached microphone */
+    /** @hide
+     * The audio output device code for a wired headphone without attached microphone */
     public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
-    /** {@hide} The audio output device code for generic Bluetooth SCO, for voice */
+    /** @hide
+     * The audio output device code for generic Bluetooth SCO, for voice */
     public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
-    /** {@hide} The audio output device code for Bluetooth SCO Headset Profile (HSP) and
-     *  Hands-Free Profile (HFP), for voice
+    /** @hide
+     * The audio output device code for Bluetooth SCO Headset Profile (HSP) and
+     * Hands-Free Profile (HFP), for voice
      */
     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET =
             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
-    /** {@hide} The audio output device code for Bluetooth SCO car audio, for voice */
+    /** @hide
+     * The audio output device code for Bluetooth SCO car audio, for voice */
     public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT =
             AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
-    /** {@hide} The audio output device code for generic Bluetooth A2DP, for music */
+    /** @hide
+     * The audio output device code for generic Bluetooth A2DP, for music */
     public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
-    /** {@hide} The audio output device code for Bluetooth A2DP headphones, for music */
+    /** @hide
+     * The audio output device code for Bluetooth A2DP headphones, for music */
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES =
             AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
-    /** {@hide} The audio output device code for Bluetooth A2DP external speaker, for music */
+    /** @hide
+     * The audio output device code for Bluetooth A2DP external speaker, for music */
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER =
             AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
-    /** {@hide} The audio output device code for S/PDIF or HDMI */
+    /** @hide
+     * The audio output device code for S/PDIF (legacy) or HDMI
+     * Deprecated: replaced by {@link #DEVICE_OUT_HDMI} */
     public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL;
-    /** {@hide} The audio output device code for an analog wired headset attached via a
+    /** @hide
+     * The audio output device code for HDMI */
+    public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI;
+    /** @hide
+     * The audio output device code for an analog wired headset attached via a
      *  docking station
      */
     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
-    /** {@hide} The audio output device code for a digital wired headset attached via a
+    /** @hide
+     * The audio output device code for a digital wired headset attached via a
      *  docking station
      */
     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
-    /** {@hide} The audio output device code for a USB audio accessory. The accessory is in USB host
+    /** @hide
+     * The audio output device code for a USB audio accessory. The accessory is in USB host
      * mode and the Android device in USB device mode
      */
     public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
-    /** {@hide} The audio output device code for a USB audio device. The device is in USB device
+    /** @hide
+     * The audio output device code for a USB audio device. The device is in USB device
      * mode and the Android device in USB host mode
      */
     public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE;
-    /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be
+    /** @hide
+     * The audio output device code for projection output.
+     */
+    public static final int DEVICE_OUT_REMOTE_SUBMIX = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+    /** @hide
+     * The audio output device code the telephony voice TX path.
+     */
+    public static final int DEVICE_OUT_TELEPHONY_TX = AudioSystem.DEVICE_OUT_TELEPHONY_TX;
+    /** @hide
+     * The audio output device code for an analog jack with line impedance detected.
+     */
+    public static final int DEVICE_OUT_LINE = AudioSystem.DEVICE_OUT_LINE;
+    /** @hide
+     * The audio output device code for HDMI Audio Return Channel.
+     */
+    public static final int DEVICE_OUT_HDMI_ARC = AudioSystem.DEVICE_OUT_HDMI_ARC;
+    /** @hide
+     * The audio output device code for S/PDIF digital connection.
+     */
+    public static final int DEVICE_OUT_SPDIF = AudioSystem.DEVICE_OUT_SPDIF;
+    /** @hide
+     * The audio output device code for built-in FM transmitter.
+     */
+    public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM;
+    /** @hide
+     * This is not used as a returned value from {@link #getDevicesForStream}, but could be
      *  used in the future in a set method to select whatever default device is chosen by the
      *  platform-specific implementation.
      */
     public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT;
 
+    /** @hide
+     * The audio input device code for default built-in microphone
+     */
+    public static final int DEVICE_IN_BUILTIN_MIC = AudioSystem.DEVICE_IN_BUILTIN_MIC;
+    /** @hide
+     * The audio input device code for a Bluetooth SCO headset
+     */
+    public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET =
+                                    AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+    /** @hide
+     * The audio input device code for wired headset microphone
+     */
+    public static final int DEVICE_IN_WIRED_HEADSET =
+                                    AudioSystem.DEVICE_IN_WIRED_HEADSET;
+    /** @hide
+     * The audio input device code for HDMI
+     */
+    public static final int DEVICE_IN_HDMI =
+                                    AudioSystem.DEVICE_IN_HDMI;
+    /** @hide
+     * The audio input device code for telephony voice RX path
+     */
+    public static final int DEVICE_IN_TELEPHONY_RX =
+                                    AudioSystem.DEVICE_IN_TELEPHONY_RX;
+    /** @hide
+     * The audio input device code for built-in microphone pointing to the back
+     */
+    public static final int DEVICE_IN_BACK_MIC =
+                                    AudioSystem.DEVICE_IN_BACK_MIC;
+    /** @hide
+     * The audio input device code for analog from a docking station
+     */
+    public static final int DEVICE_IN_ANLG_DOCK_HEADSET =
+                                    AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET;
+    /** @hide
+     * The audio input device code for digital from a docking station
+     */
+    public static final int DEVICE_IN_DGTL_DOCK_HEADSET =
+                                    AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET;
+    /** @hide
+     * The audio input device code for a USB audio accessory. The accessory is in USB host
+     * mode and the Android device in USB device mode
+     */
+    public static final int DEVICE_IN_USB_ACCESSORY =
+                                    AudioSystem.DEVICE_IN_USB_ACCESSORY;
+    /** @hide
+     * The audio input device code for a USB audio device. The device is in USB device
+     * mode and the Android device in USB host mode
+     */
+    public static final int DEVICE_IN_USB_DEVICE =
+                                    AudioSystem.DEVICE_IN_USB_DEVICE;
+    /** @hide
+     * The audio input device code for a FM radio tuner
+     */
+    public static final int DEVICE_IN_FM_TUNER = AudioSystem.DEVICE_IN_FM_TUNER;
+    /** @hide
+     * The audio input device code for a TV tuner
+     */
+    public static final int DEVICE_IN_TV_TUNER = AudioSystem.DEVICE_IN_TV_TUNER;
+    /** @hide
+     * The audio input device code for an analog jack with line impedance detected
+     */
+    public static final int DEVICE_IN_LINE = AudioSystem.DEVICE_IN_LINE;
+    /** @hide
+     * The audio input device code for a S/PDIF digital connection
+     */
+    public static final int DEVICE_IN_SPDIF = AudioSystem.DEVICE_IN_SPDIF;
+
+    /**
+     * Return true if the device code corresponds to an output device.
+     * @hide
+     */
+    public static boolean isOutputDevice(int device)
+    {
+        return (device & AudioSystem.DEVICE_BIT_IN) == 0;
+    }
+
+    /**
+     * Return true if the device code corresponds to an input device.
+     * @hide
+     */
+    public static boolean isInputDevice(int device)
+    {
+        return (device & AudioSystem.DEVICE_BIT_IN) == AudioSystem.DEVICE_BIT_IN;
+    }
+
+
     /**
      * Return the enabled devices for the specified output stream type.
      *
@@ -2635,9 +2766,17 @@
      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP},
      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES},
      *            {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER},
-     *            {@link #DEVICE_OUT_AUX_DIGITAL},
+     *            {@link #DEVICE_OUT_HDMI},
      *            {@link #DEVICE_OUT_ANLG_DOCK_HEADSET},
      *            {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}.
+     *            {@link #DEVICE_OUT_USB_ACCESSORY}.
+     *            {@link #DEVICE_OUT_USB_DEVICE}.
+     *            {@link #DEVICE_OUT_REMOTE_SUBMIX}.
+     *            {@link #DEVICE_OUT_TELEPHONY_TX}.
+     *            {@link #DEVICE_OUT_LINE}.
+     *            {@link #DEVICE_OUT_HDMI_ARC}.
+     *            {@link #DEVICE_OUT_SPDIF}.
+     *            {@link #DEVICE_OUT_FM}.
      *            {@link #DEVICE_OUT_DEFAULT} is not used here.
      *
      * The implementation may support additional device codes beyond those listed, so
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index bb8cfa6..6e623a5 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -423,7 +423,7 @@
     public final static int STREAM_REMOTE_MUSIC = -200;
 
     // Devices for which the volume is fixed and VolumePanel slider should be disabled
-    final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_AUX_DIGITAL |
+    final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
             AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
             AudioSystem.DEVICE_OUT_ALL_USB;
@@ -2895,7 +2895,7 @@
 
         public String getSettingNameForDevice(int device) {
             String name = mVolumeIndexSettingName;
-            String suffix = AudioSystem.getDeviceName(device);
+            String suffix = AudioSystem.getOutputDeviceName(device);
             if (suffix.isEmpty()) {
                 return name;
             }
@@ -3935,7 +3935,7 @@
     // sent if none of these devices is connected.
     int mBecomingNoisyIntentDevices =
             AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
-            AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_AUX_DIGITAL |
+            AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI |
             AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
             AudioSystem.DEVICE_OUT_ALL_USB;
 
@@ -3992,7 +3992,7 @@
         } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {
             connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
             intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
-        } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) {
+        } else if (device == AudioSystem.DEVICE_OUT_HDMI) {
             connType = AudioRoutesInfo.MAIN_HDMI;
             intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG);
         }
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 5ddb198..0c45443 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -234,11 +234,17 @@
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;
     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;
     public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
+    public static final int DEVICE_OUT_HDMI = DEVICE_OUT_AUX_DIGITAL;
     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;
     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
     public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
     public static final int DEVICE_OUT_USB_DEVICE = 0x4000;
     public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000;
+    public static final int DEVICE_OUT_TELEPHONY_TX = 0x10000;
+    public static final int DEVICE_OUT_LINE = 0x20000;
+    public static final int DEVICE_OUT_HDMI_ARC = 0x40000;
+    public static final int DEVICE_OUT_SPDIF = 0x80000;
+    public static final int DEVICE_OUT_FM = 0x100000;
 
     public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
 
@@ -252,12 +258,17 @@
                                               DEVICE_OUT_BLUETOOTH_A2DP |
                                               DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
                                               DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
-                                              DEVICE_OUT_AUX_DIGITAL |
+                                              DEVICE_OUT_HDMI |
                                               DEVICE_OUT_ANLG_DOCK_HEADSET |
                                               DEVICE_OUT_DGTL_DOCK_HEADSET |
                                               DEVICE_OUT_USB_ACCESSORY |
                                               DEVICE_OUT_USB_DEVICE |
                                               DEVICE_OUT_REMOTE_SUBMIX |
+                                              DEVICE_OUT_TELEPHONY_TX |
+                                              DEVICE_OUT_LINE |
+                                              DEVICE_OUT_HDMI_ARC |
+                                              DEVICE_OUT_SPDIF |
+                                              DEVICE_OUT_FM |
                                               DEVICE_OUT_DEFAULT);
     public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
                                                    DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -275,13 +286,20 @@
     public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = DEVICE_BIT_IN | 0x8;
     public static final int DEVICE_IN_WIRED_HEADSET = DEVICE_BIT_IN | 0x10;
     public static final int DEVICE_IN_AUX_DIGITAL = DEVICE_BIT_IN | 0x20;
+    public static final int DEVICE_IN_HDMI = DEVICE_IN_AUX_DIGITAL;
     public static final int DEVICE_IN_VOICE_CALL = DEVICE_BIT_IN | 0x40;
+    public static final int DEVICE_IN_TELEPHONY_RX = DEVICE_IN_VOICE_CALL;
     public static final int DEVICE_IN_BACK_MIC = DEVICE_BIT_IN | 0x80;
     public static final int DEVICE_IN_REMOTE_SUBMIX = DEVICE_BIT_IN | 0x100;
     public static final int DEVICE_IN_ANLG_DOCK_HEADSET = DEVICE_BIT_IN | 0x200;
     public static final int DEVICE_IN_DGTL_DOCK_HEADSET = DEVICE_BIT_IN | 0x400;
     public static final int DEVICE_IN_USB_ACCESSORY = DEVICE_BIT_IN | 0x800;
     public static final int DEVICE_IN_USB_DEVICE = DEVICE_BIT_IN | 0x1000;
+    public static final int DEVICE_IN_FM_TUNER = DEVICE_BIT_IN | 0x2000;
+    public static final int DEVICE_IN_TV_TUNER = DEVICE_BIT_IN | 0x4000;
+    public static final int DEVICE_IN_LINE = DEVICE_BIT_IN | 0x8000;
+    public static final int DEVICE_IN_SPDIF = DEVICE_BIT_IN | 0x10000;
+
     public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
 
     public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
@@ -289,14 +307,18 @@
                                              DEVICE_IN_BUILTIN_MIC |
                                              DEVICE_IN_BLUETOOTH_SCO_HEADSET |
                                              DEVICE_IN_WIRED_HEADSET |
-                                             DEVICE_IN_AUX_DIGITAL |
-                                             DEVICE_IN_VOICE_CALL |
+                                             DEVICE_IN_HDMI |
+                                             DEVICE_IN_TELEPHONY_RX |
                                              DEVICE_IN_BACK_MIC |
                                              DEVICE_IN_REMOTE_SUBMIX |
                                              DEVICE_IN_ANLG_DOCK_HEADSET |
                                              DEVICE_IN_DGTL_DOCK_HEADSET |
                                              DEVICE_IN_USB_ACCESSORY |
                                              DEVICE_IN_USB_DEVICE |
+                                             DEVICE_IN_FM_TUNER |
+                                             DEVICE_IN_TV_TUNER |
+                                             DEVICE_IN_LINE |
+                                             DEVICE_IN_SPDIF |
                                              DEVICE_IN_DEFAULT);
     public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
     public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
@@ -318,13 +340,19 @@
     public static final String DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME = "bt_a2dp_hp";
     public static final String DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME = "bt_a2dp_spk";
     public static final String DEVICE_OUT_AUX_DIGITAL_NAME = "aux_digital";
+    public static final String DEVICE_OUT_HDMI_NAME = "hdmi";
     public static final String DEVICE_OUT_ANLG_DOCK_HEADSET_NAME = "analog_dock";
     public static final String DEVICE_OUT_DGTL_DOCK_HEADSET_NAME = "digital_dock";
     public static final String DEVICE_OUT_USB_ACCESSORY_NAME = "usb_accessory";
     public static final String DEVICE_OUT_USB_DEVICE_NAME = "usb_device";
     public static final String DEVICE_OUT_REMOTE_SUBMIX_NAME = "remote_submix";
+    public static final String DEVICE_OUT_TELEPHONY_TX_NAME = "telephony_tx";
+    public static final String DEVICE_OUT_LINE_NAME = "line";
+    public static final String DEVICE_OUT_HDMI_ARC_NAME = "hmdi_arc";
+    public static final String DEVICE_OUT_SPDIF_NAME = "spdif";
+    public static final String DEVICE_OUT_FM_NAME = "fm_transmitter";
 
-    public static String getDeviceName(int device)
+    public static String getOutputDeviceName(int device)
     {
         switch(device) {
         case DEVICE_OUT_EARPIECE:
@@ -347,8 +375,8 @@
             return DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME;
         case DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
             return DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME;
-        case DEVICE_OUT_AUX_DIGITAL:
-            return DEVICE_OUT_AUX_DIGITAL_NAME;
+        case DEVICE_OUT_HDMI:
+            return DEVICE_OUT_HDMI_NAME;
         case DEVICE_OUT_ANLG_DOCK_HEADSET:
             return DEVICE_OUT_ANLG_DOCK_HEADSET_NAME;
         case DEVICE_OUT_DGTL_DOCK_HEADSET:
@@ -359,12 +387,23 @@
             return DEVICE_OUT_USB_DEVICE_NAME;
         case DEVICE_OUT_REMOTE_SUBMIX:
             return DEVICE_OUT_REMOTE_SUBMIX_NAME;
+        case DEVICE_OUT_TELEPHONY_TX:
+            return DEVICE_OUT_TELEPHONY_TX_NAME;
+        case DEVICE_OUT_LINE:
+            return DEVICE_OUT_LINE_NAME;
+        case DEVICE_OUT_HDMI_ARC:
+            return DEVICE_OUT_HDMI_ARC_NAME;
+        case DEVICE_OUT_SPDIF:
+            return DEVICE_OUT_SPDIF_NAME;
+        case DEVICE_OUT_FM:
+            return DEVICE_OUT_FM_NAME;
         case DEVICE_OUT_DEFAULT:
         default:
             return "";
         }
     }
 
+
     // phone state, match audio_mode???
     public static final int PHONE_STATE_OFFCALL = 0;
     public static final int PHONE_STATE_RINGING = 1;
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 37f45c2..26ae3cc 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -407,6 +407,19 @@
     }
 
     /**
+     * Get a {@link MediaSession} associated with this RCC. It will only have a
+     * session while it is registered with
+     * {@link AudioManager#registerRemoteControlClient}. The session returned
+     * should not be modified directly by the application but may be used with
+     * other APIs that require a session.
+     *
+     * @return A media session object or null.
+     */
+    public MediaSession getMediaSession() {
+        return mSession;
+    }
+
+    /**
      * Class used to modify metadata in a {@link RemoteControlClient} object.
      * Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor,
      * on which you set the metadata for the RemoteControlClient instance. Once all the information
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 2d17b7b..aae92e8 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -149,14 +149,16 @@
         if (mLockPatternUtils.checkPassword(entry)) {
             mCallback.reportUnlockAttempt(true);
             mCallback.dismiss(true);
-        } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
-            // to avoid accidental lockout, only count attempts that are long enough to be a
-            // real password. This may require some tweaking.
-            mCallback.reportUnlockAttempt(false);
-            int attempts = KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
-            if (0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
-                long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
-                handleAttemptLockout(deadline);
+        } else {
+            if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
+                // to avoid accidental lockout, only count attempts that are long enough to be a
+                // real password. This may require some tweaking.
+                mCallback.reportUnlockAttempt(false);
+                int attempts = KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
+                if (0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+                    handleAttemptLockout(deadline);
+                }
             }
             mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
         }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index f85e29f..2685447 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -16,8 +16,6 @@
 
 package com.android.keyguard;
 
-import android.nfc.NfcUnlock;
-
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
@@ -46,6 +44,7 @@
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -264,12 +263,6 @@
                 }
             }
         }
-        @Override
-        public void onNfcUnlock() {
-            if (NfcUnlock.getPropertyEnabled()) {
-                dismiss(true);
-            }
-        }
     };
 
     private static final boolean isMusicPlaying(int playbackState) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d6351df..0bcd916 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -37,7 +37,6 @@
 import static android.os.BatteryManager.EXTRA_HEALTH;
 import android.media.AudioManager;
 import android.media.IRemoteControlDisplay;
-import android.nfc.NfcUnlock;
 import android.os.BatteryManager;
 import android.os.Bundle;
 import android.os.Handler;
@@ -98,7 +97,6 @@
     protected static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
     private static final int MSG_SCREEN_TURNED_ON = 319;
     private static final int MSG_SCREEN_TURNED_OFF = 320;
-    private static final int MSG_NFC_UNLOCK = 321;
     private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
 
     private static KeyguardUpdateMonitor sInstance;
@@ -204,9 +202,6 @@
                 case MSG_SCREEN_TURNED_ON:
                     handleScreenTurnedOn();
                     break;
-                case MSG_NFC_UNLOCK:
-                    handleNfcUnlock();
-                    break;
             }
         }
     };
@@ -356,15 +351,6 @@
         }
     };
 
-    private final BroadcastReceiver mNfcUnlockReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (NfcUnlock.ACTION_NFC_UNLOCK.equals(intent.getAction())) {
-                mHandler.sendEmptyMessage(MSG_NFC_UNLOCK);
-            }
-        }
-    }
-    ;
     /**
      * When we receive a
      * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
@@ -549,15 +535,6 @@
         }
     }
 
-    private void handleNfcUnlock() {
-        for (int i = 0; i < mCallbacks.size(); i++) {
-            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
-            if (cb != null) {
-                cb.onNfcUnlock();
-            }
-        }
-    }
-
     private KeyguardUpdateMonitor(Context context) {
         mContext = context;
 
@@ -587,11 +564,6 @@
         filter.addAction(Intent.ACTION_USER_REMOVED);
         context.registerReceiver(mBroadcastReceiver, filter);
 
-        final IntentFilter nfcUnlockIntentFilter = new IntentFilter();
-        nfcUnlockIntentFilter.addAction(NfcUnlock.ACTION_NFC_UNLOCK);
-        context.registerReceiver(mNfcUnlockReceiver, nfcUnlockIntentFilter,
-                NfcUnlock.NFC_UNLOCK_PERMISSION, null /* run on default scheduler */);
-
         final IntentFilter bootCompleteFilter = new IntentFilter();
         bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 91a024f..76206f7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -179,10 +179,4 @@
      * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT}.
      */
     public void onScreenTurnedOff(int why) { }
-
-    /**
-     * Called when the NFC Service has found a tag that is registered for NFC unlock.
-     */
-    public void onNfcUnlock() { }
-
 }
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index da37803..6d101d7 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -6,10 +6,6 @@
   public void setGlowAlpha(float);
   public void setGlowScale(float);
 }
--keep class com.android.systemui.recents.views.TaskInfoView {
-	public void setCircularClipRadius(float);
-	public float getCircularClipRadius();
-}
 
 -keep class com.android.systemui.statusbar.phone.PhoneStatusBar
 -keep class com.android.systemui.statusbar.tv.TvStatusBar
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index a68ad2f..97051ff 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -22,21 +22,6 @@
         android:id="@+id/task_view_thumbnail"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
-    <com.android.systemui.recents.views.TaskInfoView
-        android:id="@+id/task_view_info_pane"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="invisible"
-        android:background="@color/recents_task_bar_default_background_color">
-        <Button
-            android:id="@+id/task_view_app_info_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="20dp"
-            android:layout_marginEnd="20dp"
-            android:layout_gravity="top|center_horizontal"
-            android:text="@string/recents_app_info_button_label" />
-    </com.android.systemui.recents.views.TaskInfoView>
     <com.android.systemui.recents.views.TaskBarView
         android:id="@+id/task_view_bar"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 6df2a19..ffd64d4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -64,10 +64,12 @@
                 mSingleCountFirstTaskRect.offset(0, (int) statusBarHeight);
                 mMultipleCountFirstTaskRect = replyData.getParcelable(KEY_MULTIPLE_TASK_STACK_RECT);
                 mMultipleCountFirstTaskRect.offset(0, (int) statusBarHeight);
-                Console.log(Constants.Log.App.RecentsComponent,
-                        "[RecentsComponent|RecentsMessageHandler|handleMessage]",
-                        "singleTaskRect: " + mSingleCountFirstTaskRect +
-                        " multipleTaskRect: " + mMultipleCountFirstTaskRect);
+                if (Console.Enabled) {
+                    Console.log(Constants.Log.App.RecentsComponent,
+                            "[RecentsComponent|RecentsMessageHandler|handleMessage]",
+                            "singleTaskRect: " + mSingleCountFirstTaskRect +
+                            " multipleTaskRect: " + mMultipleCountFirstTaskRect);
+                }
 
                 // 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.
@@ -83,9 +85,11 @@
     class RecentsServiceConnection implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName className, IBinder service) {
-            Console.log(Constants.Log.App.RecentsComponent,
-                    "[RecentsComponent|ServiceConnection|onServiceConnected]",
-                    "toggleRecents: " + mToggleRecentsUponServiceBound);
+            if (Console.Enabled) {
+                Console.log(Constants.Log.App.RecentsComponent,
+                        "[RecentsComponent|ServiceConnection|onServiceConnected]",
+                        "toggleRecents: " + mToggleRecentsUponServiceBound);
+            }
             mService = new Messenger(service);
             mServiceIsBound = true;
 
@@ -103,8 +107,10 @@
 
         @Override
         public void onServiceDisconnected(ComponentName className) {
-            Console.log(Constants.Log.App.RecentsComponent,
-                    "[RecentsComponent|ServiceConnection|onServiceDisconnected]");
+            if (Console.Enabled) {
+                Console.log(Constants.Log.App.RecentsComponent,
+                        "[RecentsComponent|ServiceConnection|onServiceDisconnected]");
+            }
             mService = null;
             mServiceIsBound = false;
         }
@@ -159,7 +165,9 @@
     }
 
     public void onStart() {
-        Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|start]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|start]");
+        }
 
         // Try to create a long-running connection to the recents service
         bindToRecentsService(false);
@@ -167,7 +175,9 @@
 
     /** Shows the recents */
     public void onShowRecents(boolean triggeredFromAltTab, View statusBarView) {
-        Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|showRecents]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|showRecents]");
+        }
         mStatusBarView = statusBarView;
         mTriggeredFromAltTab = triggeredFromAltTab;
         if (!mServiceIsBound) {
@@ -186,7 +196,9 @@
 
     /** Hides the recents */
     public void onHideRecents(boolean triggeredFromAltTab) {
-        Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|hideRecents]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|hideRecents]");
+        }
         if (mServiceIsBound) {
             // Notify recents to close it
             try {
@@ -202,12 +214,14 @@
 
     /** 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);
+        if (Console.Enabled) {
+            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) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index c8d97cc..33e05dd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -42,6 +42,9 @@
     public static final String AnsiCyan = "\u001B[36m";     // ClickEvents
     public static final String AnsiWhite = "\u001B[37m";
 
+    // Console enabled state
+    public static final boolean Enabled = false;
+
     /** Logs a key */
     public static void log(String key) {
         log(true, key, "", AnsiReset);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 79545b3..fcbd0f4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -31,8 +31,6 @@
             public static final boolean EnableTaskStackClipping = false;
             // Enables the use of theme colors as the task bar background
             public static final boolean EnableTaskBarThemeColors = true;
-            // Enables the info pane on long-pressing the task
-            public static final boolean EnableInfoPane = false;
             // Enables app-info pane on long-pressing the icon
             public static final boolean EnableDevAppInfoOnLongPress = true;
             // Enables the search bar layout
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index bae8a99..e7119f6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -80,8 +80,10 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-            Console.log(Constants.Log.App.SystemUIHandshake,
-                    "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
+            if (Console.Enabled) {
+                Console.log(Constants.Log.App.SystemUIHandshake,
+                        "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
+            }
             if (action.equals(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY)) {
                 if (intent.getBooleanExtra(RecentsService.EXTRA_TRIGGERED_FROM_ALT_TAB, false)) {
                     // Dismiss recents, launching the focused task
@@ -164,10 +166,12 @@
                     ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
                     appWidgetId = -1;
                 }
-                Console.log(Constants.Log.App.SystemUIHandshake,
-                        "[RecentsActivity|onCreate|settings|appWidgetId]",
-                        "Id: " + appWidgetId,
-                        Console.AnsiBlue);
+                if (Console.Enabled) {
+                    Console.log(Constants.Log.App.SystemUIHandshake,
+                            "[RecentsActivity|onCreate|settings|appWidgetId]",
+                            "Id: " + appWidgetId,
+                            Console.AnsiBlue);
+                }
             }
 
             // If there is no id, then bind a new search app widget
@@ -175,10 +179,12 @@
                 Pair<Integer, AppWidgetProviderInfo> widgetInfo =
                         ssp.bindSearchAppWidget(mAppWidgetHost);
                 if (widgetInfo != null) {
-                    Console.log(Constants.Log.App.SystemUIHandshake,
-                            "[RecentsActivity|onCreate|searchWidget]",
-                            "Id: " + widgetInfo.first + " Info: " + widgetInfo.second,
-                            Console.AnsiBlue);
+                    if (Console.Enabled) {
+                        Console.log(Constants.Log.App.SystemUIHandshake,
+                                "[RecentsActivity|onCreate|searchWidget]",
+                                "Id: " + widgetInfo.first + " Info: " + widgetInfo.second,
+                                Console.AnsiBlue);
+                    }
 
                     // Save the app widget id into the settings
                     config.updateSearchBarAppWidgetId(this, widgetInfo.first);
@@ -194,10 +200,12 @@
             RecentsConfiguration config = RecentsConfiguration.getInstance();
             int appWidgetId = config.searchBarAppWidgetId;
             if (appWidgetId >= 0) {
-                Console.log(Constants.Log.App.SystemUIHandshake,
-                "[RecentsActivity|onCreate|addSearchAppWidgetView]",
-                        "Id: " + appWidgetId,
-                        Console.AnsiBlue);
+                if (Console.Enabled) {
+                    Console.log(Constants.Log.App.SystemUIHandshake,
+                            "[RecentsActivity|onCreate|addSearchAppWidgetView]",
+                            "Id: " + appWidgetId,
+                            Console.AnsiBlue);
+                }
                 mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
                         mSearchAppWidgetInfo);
                 Bundle opts = new Bundle();
@@ -230,11 +238,13 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Console.logDivider(Constants.Log.App.SystemUIHandshake);
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onCreate]",
-                getIntent().getAction() + " visible: " + mVisible, Console.AnsiRed);
-        Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
-                Constants.Log.App.TimeRecentsStartupKey, "onCreate");
+        if (Console.Enabled) {
+            Console.logDivider(Constants.Log.App.SystemUIHandshake);
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onCreate]",
+                    getIntent().getAction() + " visible: " + mVisible, Console.AnsiRed);
+            Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+                    Constants.Log.App.TimeRecentsStartupKey, "onCreate");
+        }
 
         // Initialize the loader and the configuration
         RecentsTaskLoader.initialize(this);
@@ -277,11 +287,13 @@
         // Reset the task launched flag if we encounter an onNewIntent() before onStop()
         mTaskLaunched = false;
 
-        Console.logDivider(Constants.Log.App.SystemUIHandshake);
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onNewIntent]",
-                intent.getAction() + " visible: " + mVisible, Console.AnsiRed);
-        Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
-                Constants.Log.App.TimeRecentsStartupKey, "onNewIntent");
+        if (Console.Enabled) {
+            Console.logDivider(Constants.Log.App.SystemUIHandshake);
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onNewIntent]",
+                    intent.getAction() + " visible: " + mVisible, Console.AnsiRed);
+            Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+                    Constants.Log.App.TimeRecentsStartupKey, "onNewIntent");
+        }
 
         // Initialize the loader and the configuration
         RecentsTaskLoader.initialize(this);
@@ -296,8 +308,10 @@
 
     @Override
     protected void onStart() {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStart]", "",
-                Console.AnsiRed);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStart]", "",
+                    Console.AnsiRed);
+        }
         super.onStart();
         mAppWidgetHost.startListening();
         mVisible = true;
@@ -305,16 +319,20 @@
 
     @Override
     protected void onResume() {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onResume]", "",
-                Console.AnsiRed);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onResume]", "",
+                    Console.AnsiRed);
+        }
         super.onResume();
     }
 
     @Override
     public void onAttachedToWindow() {
-        Console.log(Constants.Log.App.SystemUIHandshake,
-                "[RecentsActivity|onAttachedToWindow]", "",
-                Console.AnsiRed);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake,
+                    "[RecentsActivity|onAttachedToWindow]", "",
+                    Console.AnsiRed);
+        }
         super.onAttachedToWindow();
 
         // Register the broadcast receiver to handle messages from our service
@@ -334,9 +352,11 @@
 
     @Override
     public void onDetachedFromWindow() {
-        Console.log(Constants.Log.App.SystemUIHandshake,
-                "[RecentsActivity|onDetachedFromWindow]", "",
-                Console.AnsiRed);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake,
+                    "[RecentsActivity|onDetachedFromWindow]", "",
+                    Console.AnsiRed);
+        }
         super.onDetachedFromWindow();
 
         // Unregister any broadcast receivers we have registered
@@ -347,15 +367,19 @@
 
     @Override
     protected void onPause() {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onPause]", "",
-                Console.AnsiRed);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onPause]", "",
+                    Console.AnsiRed);
+        }
         super.onPause();
     }
 
     @Override
     protected void onStop() {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStop]", "",
-                Console.AnsiRed);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStop]", "",
+                    Console.AnsiRed);
+        }
         super.onStop();
 
         mAppWidgetHost.stopListening();
@@ -365,8 +389,10 @@
 
     @Override
     protected void onDestroy() {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onDestroy]", "",
-                Console.AnsiRed);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onDestroy]", "",
+                    Console.AnsiRed);
+        }
         super.onDestroy();
     }
 
@@ -394,16 +420,9 @@
     public void onBackPressed() {
         boolean interceptedByInfoPanelClose = false;
 
-        // Try and return from any open info panes
-        if (Constants.DebugFlags.App.EnableInfoPane) {
-            interceptedByInfoPanelClose = mRecentsView.closeOpenInfoPanes();
-        }
-
-        // If we haven't been intercepted already, then unfilter any stacks
-        if (!interceptedByInfoPanelClose) {
-            if (!mRecentsView.unfilterFilteredStacks()) {
-                super.onBackPressed();
-            }
+        // Unfilter any stacks
+        if (!mRecentsView.unfilterFilteredStacks()) {
+            super.onBackPressed();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 8399551..d899c7b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -95,9 +95,11 @@
                 Configuration.ORIENTATION_LANDSCAPE;
         transposeSearchLayoutWithOrientation =
                 res.getBoolean(R.bool.recents_transpose_search_layout_with_orientation);
-        Console.log(Constants.Log.UI.MeasureAndLayout,
-                "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
-                Console.AnsiGreen);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.MeasureAndLayout,
+                    "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
+                    Console.AnsiGreen);
+        }
 
         displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
         animationPxMovementPerSecond =
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 1c04cb1..4bdbb20 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -45,8 +45,10 @@
 
     @Override
     public void handleMessage(Message msg) {
-        Console.log(Constants.Log.App.SystemUIHandshake,
-                "[RecentsService|handleMessage]", msg);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake,
+                    "[RecentsService|handleMessage]", msg);
+        }
 
         Context context = mContext.get();
         if (context == null) return;
@@ -139,31 +141,41 @@
 
     @Override
     public void onCreate() {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onCreate]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onCreate]");
+        }
         super.onCreate();
     }
 
     @Override
     public IBinder onBind(Intent intent) {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onBind]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onBind]");
+        }
         return mSystemUIMessenger.getBinder();
     }
 
     @Override
     public boolean onUnbind(Intent intent) {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onUnbind]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onUnbind]");
+        }
         return super.onUnbind(intent);
     }
 
     @Override
     public void onRebind(Intent intent) {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onRebind]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onRebind]");
+        }
         super.onRebind(intent);
     }
 
     @Override
     public void onDestroy() {
-        Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onDestroy]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsService|onDestroy]");
+        }
         super.onDestroy();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 1c12ac2..4685186 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -50,7 +50,9 @@
 
     /** Adds a new task to the load queue */
     void addTask(Task t, boolean forceLoad) {
-        Console.log(Constants.Log.App.TaskDataLoader, "  [TaskResourceLoadQueue|addTask]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "  [TaskResourceLoadQueue|addTask]");
+        }
         if (!mQueue.contains(t)) {
             mQueue.add(t);
         }
@@ -67,7 +69,9 @@
      * force reloaded.
      */
     Pair<Task, Boolean> nextTask() {
-        Console.log(Constants.Log.App.TaskDataLoader, "  [TaskResourceLoadQueue|nextTask]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "  [TaskResourceLoadQueue|nextTask]");
+        }
         Task task = mQueue.poll();
         Boolean forceLoadTask = null;
         if (task != null) {
@@ -81,14 +85,18 @@
 
     /** Removes a task from the load queue */
     void removeTask(Task t) {
-        Console.log(Constants.Log.App.TaskDataLoader, "  [TaskResourceLoadQueue|removeTask]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "  [TaskResourceLoadQueue|removeTask]");
+        }
         mQueue.remove(t);
         mForceLoadSet.remove(t.key);
     }
 
     /** Clears all the tasks from the load queue */
     void clearTasks() {
-        Console.log(Constants.Log.App.TaskDataLoader, "  [TaskResourceLoadQueue|clearTasks]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "  [TaskResourceLoadQueue|clearTasks]");
+        }
         mQueue.clear();
         mForceLoadSet.clear();
     }
@@ -131,7 +139,9 @@
 
     /** Restarts the loader thread */
     void start(Context context) {
-        Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|start]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|start]");
+        }
         mContext = context;
         mCancelled = false;
         mSystemServicesProxy = new SystemServicesProxy(context);
@@ -143,7 +153,9 @@
 
     /** Requests the loader thread to stop after the current iteration */
     void stop() {
-        Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|stop]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|stop]");
+        }
         // Mark as cancelled for the thread to pick up
         mCancelled = true;
         mSystemServicesProxy = null;
@@ -157,19 +169,25 @@
     @Override
     public void run() {
         while (true) {
-            Console.log(Constants.Log.App.TaskDataLoader,
-                    "[TaskResourceLoader|run|" + Thread.currentThread().getId() + "]");
-            if (mCancelled) {
+            if (Console.Enabled) {
                 Console.log(Constants.Log.App.TaskDataLoader,
-                        "[TaskResourceLoader|cancel|" + Thread.currentThread().getId() + "]");
+                        "[TaskResourceLoader|run|" + Thread.currentThread().getId() + "]");
+            }
+            if (mCancelled) {
+                if (Console.Enabled) {
+                    Console.log(Constants.Log.App.TaskDataLoader,
+                            "[TaskResourceLoader|cancel|" + Thread.currentThread().getId() + "]");
+                }
                 // We have to unset the context here, since the background thread may be using it
                 // when we call stop()
                 mContext = null;
                 // If we are cancelled, then wait until we are started again
                 synchronized(mLoadThread) {
                     try {
-                        Console.log(Constants.Log.App.TaskDataLoader,
-                                "[TaskResourceLoader|waitOnLoadThreadCancelled]");
+                        if (Console.Enabled) {
+                            Console.log(Constants.Log.App.TaskDataLoader,
+                                    "[TaskResourceLoader|waitOnLoadThreadCancelled]");
+                        }
                         mLoadThread.wait();
                     } catch (InterruptedException ie) {
                         ie.printStackTrace();
@@ -185,10 +203,12 @@
                 if (t != null) {
                     Drawable loadIcon = mApplicationIconCache.get(t.key);
                     Bitmap loadThumbnail = mThumbnailCache.get(t.key);
-                    Console.log(Constants.Log.App.TaskDataLoader,
-                            "  [TaskResourceLoader|load]",
-                            t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
-                                    " forceLoad: " + forceLoadTask);
+                    if (Console.Enabled) {
+                        Console.log(Constants.Log.App.TaskDataLoader,
+                                "  [TaskResourceLoader|load]",
+                                t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
+                                        " forceLoad: " + forceLoadTask);
+                    }
                     // Load the application icon
                     if (loadIcon == null || forceLoadTask) {
                         ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
@@ -196,9 +216,10 @@
                         Drawable icon = ssp.getActivityIcon(info, t.userId);
                         if (!mCancelled) {
                             if (icon != null) {
-                                Console.log(Constants.Log.App.TaskDataLoader,
-                                        "    [TaskResourceLoader|loadIcon]",
-                                        icon);
+                                if (Console.Enabled) {
+                                    Console.log(Constants.Log.App.TaskDataLoader,
+                                            "    [TaskResourceLoader|loadIcon]", icon);
+                                }
                                 loadIcon = icon;
                                 mApplicationIconCache.put(t.key, icon);
                             }
@@ -209,9 +230,10 @@
                         Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
                         if (!mCancelled) {
                             if (thumbnail != null) {
-                                Console.log(Constants.Log.App.TaskDataLoader,
-                                        "    [TaskResourceLoader|loadThumbnail]",
-                                        thumbnail);
+                                if (Console.Enabled) {
+                                    Console.log(Constants.Log.App.TaskDataLoader,
+                                            "    [TaskResourceLoader|loadThumbnail]", thumbnail);
+                                }
                                 thumbnail.setHasAlpha(false);
                                 loadThumbnail = thumbnail;
                                 mThumbnailCache.put(t.key, thumbnail);
@@ -239,8 +261,10 @@
                 if (!mCancelled && mLoadQueue.isEmpty()) {
                     synchronized(mLoadQueue) {
                         try {
-                            Console.log(Constants.Log.App.TaskDataLoader,
-                                    "[TaskResourceLoader|waitOnLoadQueue]");
+                            if (Console.Enabled) {
+                                Console.log(Constants.Log.App.TaskDataLoader,
+                                        "[TaskResourceLoader|waitOnLoadQueue]");
+                            }
                             mWaitingOnLoadQueue = true;
                             mLoadQueue.wait();
                             mWaitingOnLoadQueue = false;
@@ -320,9 +344,11 @@
         int thumbnailCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 :
                 mMaxThumbnailCacheSize;
 
-        Console.log(Constants.Log.App.TaskDataLoader,
-                "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
-                " iconCache: " + iconCacheSize);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader,
+                    "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
+                    " iconCache: " + iconCacheSize);
+        }
 
         // Initialize the proxy, cache and loaders
         mSystemServicesProxy = new SystemServicesProxy(context);
@@ -338,9 +364,11 @@
         mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
         mDefaultThumbnail.eraseColor(0x00000000);
         mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
-        Console.log(Constants.Log.App.TaskDataLoader,
-                "[RecentsTaskLoader|defaultBitmaps]",
-                "icon: " + mDefaultApplicationIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader,
+                    "[RecentsTaskLoader|defaultBitmaps]",
+                    "icon: " + mDefaultApplicationIcon + " thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
+        }
     }
 
     /** Initializes the recents task loader */
@@ -368,11 +396,13 @@
         List<ActivityManager.RecentTaskInfo> tasks =
                 ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
         Collections.reverse(tasks);
-        Console.log(Constants.Log.App.TimeSystemCalls,
-                "[RecentsTaskLoader|getRecentTasks]",
-                "" + (System.currentTimeMillis() - t1) + "ms");
-        Console.log(Constants.Log.App.TaskDataLoader,
-                "[RecentsTaskLoader|tasks]", "" + tasks.size());
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TimeSystemCalls,
+                    "[RecentsTaskLoader|getRecentTasks]",
+                    "" + (System.currentTimeMillis() - t1) + "ms");
+            Console.log(Constants.Log.App.TaskDataLoader,
+                    "[RecentsTaskLoader|tasks]", "" + tasks.size());
+        }
 
         return tasks;
     }
@@ -381,7 +411,9 @@
     SpaceNode reload(Context context, int preloadCount) {
         long t1 = System.currentTimeMillis();
 
-        Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
+        }
         Resources res = context.getResources();
         ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
         TaskStack stack = new TaskStack(context);
@@ -419,9 +451,11 @@
 
             // Preload the specified number of apps
             if (i >= (taskCount - preloadCount)) {
-                Console.log(Constants.Log.App.TaskDataLoader,
-                        "[RecentsTaskLoader|preloadTask]",
-                        "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
+                if (Console.Enabled) {
+                    Console.log(Constants.Log.App.TaskDataLoader,
+                            "[RecentsTaskLoader|preloadTask]",
+                            "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
+                }
 
                 // Load the icon (if possible and not the foremost task, from the cache)
                 if (!isForemostTask) {
@@ -451,8 +485,10 @@
                     }
                 }
                 if (task.thumbnail == null) {
-                    Console.log(Constants.Log.App.TaskDataLoader,
-                            "[RecentsTaskLoader|loadingTaskThumbnail]");
+                    if (Console.Enabled) {
+                        Console.log(Constants.Log.App.TaskDataLoader,
+                                "[RecentsTaskLoader|loadingTaskThumbnail]");
+                    }
                     task.thumbnail = ssp.getTaskThumbnail(task.key.id);
                     if (task.thumbnail != null) {
                         task.thumbnail.setHasAlpha(false);
@@ -464,13 +500,17 @@
             }
 
             // Add the task to the stack
-            Console.log(Constants.Log.App.TaskDataLoader,
-                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
+            if (Console.Enabled) {
+                Console.log(Constants.Log.App.TaskDataLoader,
+                        "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
+            }
             stack.addTask(task);
         }
-        Console.log(Constants.Log.App.TimeSystemCalls,
-                "[RecentsTaskLoader|getAllTaskTopThumbnail]",
-                "" + (System.currentTimeMillis() - t1) + "ms");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TimeSystemCalls,
+                    "[RecentsTaskLoader|getAllTaskTopThumbnail]",
+                    "" + (System.currentTimeMillis() - t1) + "ms");
+        }
 
         /*
         // Get all the stacks
@@ -505,9 +545,11 @@
         Drawable applicationIcon = mApplicationIconCache.get(t.key);
         Bitmap thumbnail = mThumbnailCache.get(t.key);
 
-        Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
-                t + " applicationIcon: " + applicationIcon + " thumbnail: " + thumbnail +
-                        " thumbnailCacheSize: " + mThumbnailCache.size());
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
+                    t + " applicationIcon: " + applicationIcon + " thumbnail: " + thumbnail +
+                            " thumbnailCacheSize: " + mThumbnailCache.size());
+        }
 
         boolean requiresLoad = false;
         if (applicationIcon == null) {
@@ -526,9 +568,11 @@
 
     /** Releases the task resource data back into the pool. */
     public void unloadTaskData(Task t) {
-        Console.log(Constants.Log.App.TaskDataLoader,
-                "[RecentsTaskLoader|unloadTask]", t +
-                " thumbnailCacheSize: " + mThumbnailCache.size());
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader,
+                    "[RecentsTaskLoader|unloadTask]", t +
+                    " thumbnailCacheSize: " + mThumbnailCache.size());
+        }
 
         mLoadQueue.removeTask(t);
         t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
@@ -536,8 +580,10 @@
 
     /** Completely removes the resource data from the pool. */
     public void deleteTaskData(Task t, boolean notifyTaskDataUnloaded) {
-        Console.log(Constants.Log.App.TaskDataLoader,
-                "[RecentsTaskLoader|deleteTask]", t);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader,
+                    "[RecentsTaskLoader|deleteTask]", t);
+        }
 
         mLoadQueue.removeTask(t);
         mThumbnailCache.remove(t.key);
@@ -549,7 +595,9 @@
 
     /** Stops the task loader and clears all pending tasks */
     void stopLoader() {
-        Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|stopLoader]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|stopLoader]");
+        }
         mLoader.stop();
         mLoadQueue.clearTasks();
     }
@@ -570,8 +618,10 @@
      * out of memory.
      */
     void onTrimMemory(int level) {
-        Console.log(Constants.Log.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
-                Console.trimMemoryLevelToString(level));
+        if (Console.Enabled) {
+            Console.log(Constants.Log.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
+                    Console.trimMemoryLevelToString(level));
+        }
 
         switch (level) {
             case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 59d0ea6..7a3ffb8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -106,7 +106,8 @@
                 rti.description = description;
                 if (i % 2 == 0) {
                     rti.taskDescription = new ActivityManager.TaskDescription(description,
-                        Bitmap.createBitmap(mDummyIcon), new Random().nextInt());
+                        Bitmap.createBitmap(mDummyIcon),
+                        0xFF000000 | (0xFFFFFF & new Random().nextInt()));
                 } else {
                     rti.taskDescription = new ActivityManager.TaskDescription();
                 }
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 c63e688..cad9ce5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -110,16 +110,20 @@
                     TaskView tv = (TaskView) stackView.getChildAt(j);
                     Task task = tv.getTask();
                     if (tv.isFocusedTask()) {
-                        Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
-                                "Found focused Task");
+                        if (Console.Enabled) {
+                            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");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
+                    "No Tasks focused");
+        }
         return false;
     }
 
@@ -168,9 +172,11 @@
                 mSearchBar.setVisibility(mHasTasks ? View.VISIBLE : View.GONE);
                 addView(mSearchBar);
 
-                Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsView|setSearchBar]",
-                        "" + (mSearchBar.getVisibility() == View.VISIBLE),
-                        Console.AnsiBlue);
+                if (Console.Enabled) {
+                    Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsView|setSearchBar]",
+                            "" + (mSearchBar.getVisibility() == View.VISIBLE),
+                            Console.AnsiBlue);
+                }
             }
         }
     }
@@ -185,10 +191,12 @@
         int height = MeasureSpec.getSize(heightMeasureSpec);
         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 
-        Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|measure]",
-                "width: " + width + " height: " + height, Console.AnsiGreen);
-        Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
-                Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|measure]",
+                    "width: " + width + " height: " + height, Console.AnsiGreen);
+            Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+                    Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
+        }
 
         // Get the search bar bounds and measure the search bar layout
         RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -227,10 +235,12 @@
      */
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|layout]",
-                new Rect(left, top, right, bottom) + " changed: " + changed, Console.AnsiGreen);
-        Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
-                Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onLayout");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|layout]",
+                    new Rect(left, top, right, bottom) + " changed: " + changed, Console.AnsiGreen);
+            Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
+                    Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onLayout");
+        }
 
         // Get the search bar bounds so that we lay it out
         RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -283,15 +293,19 @@
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        Console.log(Constants.Log.UI.Draw, "[RecentsView|dispatchDraw]", "",
-                Console.AnsiPurple);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.Draw, "[RecentsView|dispatchDraw]", "",
+                    Console.AnsiPurple);
+        }
         super.dispatchDraw(canvas);
     }
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        Console.log(Constants.Log.UI.MeasureAndLayout,
-                "[RecentsView|fitSystemWindows]", "insets: " + insets, Console.AnsiGreen);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.MeasureAndLayout,
+                    "[RecentsView|fitSystemWindows]", "insets: " + insets, Console.AnsiGreen);
+        }
 
         // Update the configuration with the latest system insets and trigger a relayout
         RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -301,24 +315,6 @@
         return insets.consumeSystemWindowInsets(false, false, false, true);
     }
 
-    /** Closes any open info panes */
-    public boolean closeOpenInfoPanes() {
-        if (mBSP != null) {
-            // 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;
-                    if (stackView.closeOpenInfoPanes()) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
     /** Unfilters any filtered stacks */
     public boolean unfilterFilteredStacks() {
         if (mBSP != null) {
@@ -346,9 +342,6 @@
             mCb.onTaskLaunching();
         }
 
-        // Close any open info panes
-        closeOpenInfoPanes();
-
         final Runnable launchRunnable = new Runnable() {
             @Override
             public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
index c34300c..3ee0545 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
@@ -178,9 +178,11 @@
     }
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        Console.log(Constants.Log.UI.TouchEvents,
-                "[SwipeHelper|interceptTouchEvent]",
-                Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.TouchEvents,
+                    "[SwipeHelper|interceptTouchEvent]",
+                    Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        }
         final int action = ev.getAction();
 
         switch (action) {
@@ -291,9 +293,11 @@
     }
 
     public boolean onTouchEvent(MotionEvent ev) {
-        Console.log(Constants.Log.UI.TouchEvents,
-                "[SwipeHelper|touchEvent]",
-                Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.TouchEvents,
+                    "[SwipeHelper|touchEvent]",
+                    Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        }
 
         if (!mDragging) {
             if (!onInterceptTouchEvent(ev)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
deleted file mode 100644
index 7b6572b..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
+++ /dev/null
@@ -1,185 +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.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.Path;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.RippleDrawable;
-import android.util.AttributeSet;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.Utilities;
-import com.android.systemui.recents.model.Task;
-
-
-/* The task info view */
-class TaskInfoView extends FrameLayout {
-
-    Button mAppInfoButton;
-
-    // Circular clip animation
-    boolean mCircularClipEnabled;
-    Path mClipPath = new Path();
-    float mClipRadius;
-    float mMaxClipRadius;
-    Point mClipOrigin = new Point();
-    ObjectAnimator mCircularClipAnimator;
-
-    public TaskInfoView(Context context) {
-        this(context, null);
-    }
-
-    public TaskInfoView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        // Initialize the buttons on the info panel
-        mAppInfoButton = (Button) findViewById(R.id.task_view_app_info_button);
-    }
-
-    /** Updates the positions of each of the items to fit in the rect specified */
-    void updateContents(Rect visibleRect) {
-        // Offset the app info button
-        mAppInfoButton.setTranslationY(visibleRect.top +
-                (visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2);
-    }
-
-    /** Sets the circular clip radius on this panel */
-    public void setCircularClipRadius(float r) {
-        mClipRadius = r;
-        invalidate();
-    }
-
-    /** Gets the circular clip radius on this panel */
-    public float getCircularClipRadius() {
-        return mClipRadius;
-    }
-
-    /** Animates the circular clip radius on the icon */
-    void animateCircularClip(Point o, float fromRadius, float toRadius,
-                             final Runnable postRunnable, boolean animateInContent) {
-        if (mCircularClipAnimator != null) {
-            mCircularClipAnimator.cancel();
-        }
-
-        // Calculate the max clip radius to each of the corners
-        int w = getMeasuredWidth() - o.x;
-        int h = getMeasuredHeight() - o.y;
-        // origin to tl, tr, br, bl
-        mMaxClipRadius = (int) Math.ceil(Math.sqrt(o.x * o.x + o.y * o.y));
-        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + o.y * o.y)));
-        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + h * h)));
-        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(o.x * o.x + h * h)));
-
-        mClipOrigin.set(o.x, o.y);
-        mClipRadius = fromRadius;
-        int duration = Utilities.calculateTranslationAnimationDuration((int) mMaxClipRadius);
-        mCircularClipAnimator = ObjectAnimator.ofFloat(this, "circularClipRadius", toRadius);
-        mCircularClipAnimator.setDuration(duration);
-        mCircularClipAnimator.setInterpolator(
-                RecentsConfiguration.getInstance().defaultBezierInterpolator);
-        mCircularClipAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mCircularClipEnabled = false;
-                if (postRunnable != null) {
-                    postRunnable.run();
-                }
-            }
-        });
-        mCircularClipAnimator.start();
-        mCircularClipEnabled = true;
-
-        if (animateInContent) {
-            animateAppInfoButtonIn(duration);
-        }
-    }
-
-    /** Cancels the circular clip animation. */
-    void cancelCircularClipAnimation() {
-        if (mCircularClipAnimator != null) {
-            mCircularClipAnimator.cancel();
-        }
-    }
-
-    void animateAppInfoButtonIn(int duration) {
-        mAppInfoButton.setScaleX(0.75f);
-        mAppInfoButton.setScaleY(0.75f);
-        mAppInfoButton.animate()
-                .scaleX(1f)
-                .scaleY(1f)
-                .setDuration(duration)
-                .setInterpolator(RecentsConfiguration.getInstance().defaultBezierInterpolator)
-                .withLayer()
-                .start();
-    }
-
-    /** Binds the info view to the task */
-    void rebindToTask(Task t, boolean animate) {
-        RecentsConfiguration configuration = RecentsConfiguration.getInstance();
-        if (Constants.DebugFlags.App.EnableTaskBarThemeColors && t.colorPrimary != 0) {
-            setBackgroundColor(t.colorPrimary);
-            // Workaround: The button currently doesn't support setting a custom background tint
-            // not defined in the theme.  Just lower the alpha on the button to make it blend more
-            // into the background.
-            if (mAppInfoButton.getBackground() instanceof RippleDrawable) {
-                RippleDrawable d = (RippleDrawable) mAppInfoButton.getBackground();
-                if (d != null) {
-                    d.setAlpha(96);
-                }
-            }
-        } else {
-            setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
-        }
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        int saveCount = 0;
-        if (mCircularClipEnabled) {
-            saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
-            mClipPath.reset();
-            mClipPath.addCircle(mClipOrigin.x, mClipOrigin.y, mClipRadius * mMaxClipRadius,
-                    Path.Direction.CW);
-            canvas.clipPath(mClipPath);
-        }
-        super.draw(canvas);
-        if (mCircularClipEnabled) {
-            canvas.restoreToCount(saveCount);
-        }
-    }
-}
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 37c3c35..3e418ca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -54,7 +54,7 @@
 /* The visual representation of a task stack view */
 public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
         TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
-        View.OnClickListener, View.OnLongClickListener, RecentsPackageMonitor.PackageCallbacks {
+        View.OnClickListener, RecentsPackageMonitor.PackageCallbacks {
 
     /** The TaskView callbacks */
     interface TaskStackViewCallbacks {
@@ -79,7 +79,6 @@
     int mMinScroll;
     int mMaxScroll;
     int mStashedScroll;
-    int mLastInfoPaneStackScroll;
     int mFocusedTaskIndex = -1;
     OverScroller mScroller;
     ObjectAnimator mScrollAnimator;
@@ -114,8 +113,10 @@
         requestSynchronizeStackViewsWithModel(0);
     }
     void requestSynchronizeStackViewsWithModel(int duration) {
-        Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
-                "[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
+                    "[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
+        }
         if (!mStackViewsDirty) {
             invalidate();
         }
@@ -222,9 +223,11 @@
 
     /** Synchronizes the views with the model */
     void synchronizeStackViewsWithModel() {
-        Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
-                "[TaskStackView|synchronizeViewsWithModel]",
-                "mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
+                    "[TaskStackView|synchronizeViewsWithModel]",
+                    "mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
+        }
         if (mStackViewsDirty) {
             // XXX: Consider using TaskViewTransform pool to prevent allocations
             // XXX: Iterate children views, update transforms and remove all that are not visible
@@ -278,8 +281,10 @@
                 }
             }
 
-            Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
-                    "  [TaskStackView|viewChildren]", "" + getChildCount());
+            if (Console.Enabled) {
+                Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
+                        "  [TaskStackView|viewChildren]", "" + getChildCount());
+            }
 
             mStackViewsAnimationDuration = 0;
             mStackViewsDirty = false;
@@ -290,17 +295,6 @@
     public void setStackScroll(int value) {
         mStackScroll = value;
         requestSynchronizeStackViewsWithModel();
-
-        // Close any open info panes if the user has scrolled away from them
-        boolean isAnimatingScroll = (mScrollAnimator != null && mScrollAnimator.isRunning());
-        if (mLastInfoPaneStackScroll > -1 && !isAnimatingScroll) {
-            RecentsConfiguration config = RecentsConfiguration.getInstance();
-            if (Math.abs(mStackScroll - mLastInfoPaneStackScroll) >
-                    config.taskStackScrollDismissInfoPaneDistance) {
-                // Close any open info panes
-                closeOpenInfoPanes();
-            }
-        }
     }
     /** Sets the current stack scroll without synchronizing the stack view with the model */
     public void setStackScrollRaw(int value) {
@@ -455,24 +449,11 @@
         }
     }
 
-    /** Closes any open info panes. */
-    boolean closeOpenInfoPanes() {
-        if (!Constants.DebugFlags.App.EnableInfoPane) return false;
-
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            TaskView tv = (TaskView) getChildAt(i);
-            if (tv.isInfoPaneVisible()) {
-                tv.hideInfoPane();
-                return true;
-            }
-        }
-        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 (Console.Enabled) {
+            Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "" + taskIndex);
+        }
         if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
             mFocusedTaskIndex = taskIndex;
 
@@ -482,7 +463,9 @@
             Runnable postScrollRunnable = null;
             if (tv != null) {
                 tv.setFocusedTask();
-                Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "Requesting focus");
+                if (Console.Enabled) {
+                    Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "Requesting focus");
+                }
             } else {
                 postScrollRunnable = new Runnable() {
                     @Override
@@ -491,8 +474,10 @@
                         TaskView tv = getChildViewForTask(t);
                         if (tv != null) {
                             tv.setFocusedTask();
-                            Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]",
-                                    "Requesting focus after scroll animation");
+                            if (Console.Enabled) {
+                                Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]",
+                                        "Requesting focus after scroll animation");
+                            }
                         }
                     }
                 };
@@ -514,7 +499,10 @@
 
     /** Focuses the next task in the stack */
     void focusNextTask(boolean forward) {
-        Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusNextTask]", "" + mFocusedTaskIndex);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusNextTask]", "" +
+                    mFocusedTaskIndex);
+        }
 
         // Find the next index to focus
         int numTasks = mStack.getTaskCount();
@@ -530,9 +518,11 @@
 
     /** Enables the hw layers and increments the hw layer requirement ref count */
     void addHwLayersRefCount(String reason) {
-        Console.log(Constants.Log.UI.HwLayers,
-                "[TaskStackView|addHwLayersRefCount] refCount: " +
-                        mHwLayersRefCount + "->" + (mHwLayersRefCount + 1) + " " + reason);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.HwLayers,
+                    "[TaskStackView|addHwLayersRefCount] refCount: " +
+                            mHwLayersRefCount + "->" + (mHwLayersRefCount + 1) + " " + reason);
+        }
         if (mHwLayersRefCount == 0) {
             // Enable hw layers on each of the children
             int childCount = getChildCount();
@@ -547,9 +537,11 @@
     /** Decrements the hw layer requirement ref count and disables the hw layers when we don't
         need them anymore. */
     void decHwLayersRefCount(String reason) {
-        Console.log(Constants.Log.UI.HwLayers,
-                "[TaskStackView|decHwLayersRefCount] refCount: " +
-                        mHwLayersRefCount + "->" + (mHwLayersRefCount - 1) + " " + reason);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.HwLayers,
+                    "[TaskStackView|decHwLayersRefCount] refCount: " +
+                            mHwLayersRefCount + "->" + (mHwLayersRefCount - 1) + " " + reason);
+        }
         mHwLayersRefCount--;
         if (mHwLayersRefCount == 0) {
             // Disable hw layers on each of the children
@@ -589,8 +581,10 @@
 
     @Override
     public void dispatchDraw(Canvas canvas) {
-        Console.log(Constants.Log.UI.Draw, "[TaskStackView|dispatchDraw]", "",
-                Console.AnsiPurple);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.Draw, "[TaskStackView|dispatchDraw]", "",
+                    Console.AnsiPurple);
+        }
         synchronizeStackViewsWithModel();
         super.dispatchDraw(canvas);
     }
@@ -674,9 +668,11 @@
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int width = MeasureSpec.getSize(widthMeasureSpec);
         int height = MeasureSpec.getSize(heightMeasureSpec);
-        Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|measure]",
-                "width: " + width + " height: " + height +
-                " awaitingFirstLayout: " + mAwaitingFirstLayout, Console.AnsiGreen);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|measure]",
+                    "width: " + width + " height: " + height +
+                            " awaitingFirstLayout: " + mAwaitingFirstLayout, Console.AnsiGreen);
+        }
 
         // Compute our stack/task rects
         RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -731,8 +727,10 @@
      */
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|layout]",
-                "" + new Rect(left, top, right, bottom), Console.AnsiGreen);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|layout]",
+                    "" + new Rect(left, top, right, bottom), Console.AnsiGreen);
+        }
 
         // Debug logging
         if (Constants.Log.UI.MeasureAndLayout) {
@@ -949,9 +947,6 @@
     @Override
     public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curTasks,
                                 Task filteredTask) {
-        // Close any open info panes
-        closeOpenInfoPanes();
-
         // Stash the scroll and filtered task for us to restore to when we unfilter
         mStashedScroll = getStackScroll();
 
@@ -976,9 +971,6 @@
 
     @Override
     public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curTasks) {
-        // Close any open info panes
-        closeOpenInfoPanes();
-
         // Calculate the current task transforms
         final ArrayList<TaskViewTransform> curTaskTransforms =
                 getStackTransforms(curTasks, getStackScroll(), null, true);
@@ -1004,7 +996,9 @@
 
     @Override
     public TaskView createView(Context context) {
-        Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|createPoolView]");
+        if (Console.Enabled) {
+            Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|createPoolView]");
+        }
         return (TaskView) mInflater.inflate(R.layout.recents_task_view, this, false);
     }
 
@@ -1012,8 +1006,10 @@
     public void prepareViewToEnterPool(TaskView tv) {
         Task task = tv.getTask();
         tv.resetViewProperties();
-        Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|returnToPool]",
-                tv.getTask() + " tv: " + tv);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|returnToPool]",
+                    tv.getTask() + " tv: " + tv);
+        }
 
         // Report that this tasks's data is no longer being used
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -1028,8 +1024,10 @@
 
     @Override
     public void prepareViewToLeavePool(TaskView tv, Task prepareData, boolean isNewView) {
-        Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|leavePool]",
-                "isNewView: " + isNewView);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|leavePool]",
+                    "isNewView: " + isNewView);
+        }
 
         // Setup and attach the view to the window
         Task task = prepareData;
@@ -1051,16 +1049,15 @@
         }
 
         // Add/attach the view to the hierarchy
-        Console.log(Constants.Log.ViewPool.PoolCallbacks, "  [TaskStackView|insertIndex]",
-                "" + insertIndex);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.ViewPool.PoolCallbacks, "  [TaskStackView|insertIndex]",
+                    "" + insertIndex);
+        }
         if (isNewView) {
             addView(tv, insertIndex);
 
             // Set the callbacks and listeners for this new view
             tv.setOnClickListener(this);
-            if (Constants.DebugFlags.App.EnableInfoPane) {
-                tv.setOnLongClickListener(this);
-            }
             tv.setCallbacks(this);
         } else {
             attachViewToParent(tv, insertIndex, tv.getLayoutParams());
@@ -1081,9 +1078,11 @@
 
     @Override
     public void onTaskIconClicked(TaskView tv) {
-        Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Icon]",
-                tv.getTask() + " is currently filtered: " + mStack.hasFilteredTasks(),
-                Console.AnsiCyan);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Icon]",
+                    tv.getTask() + " is currently filtered: " + mStack.hasFilteredTasks(),
+                    Console.AnsiCyan);
+        }
         if (Constants.DebugFlags.App.EnableTaskFiltering) {
             if (mStack.hasFilteredTasks()) {
                 mStack.unfilterTasks();
@@ -1094,17 +1093,6 @@
     }
 
     @Override
-    public void onTaskInfoPanelShown(TaskView tv) {
-        // Do nothing
-    }
-
-    @Override
-    public void onTaskInfoPanelHidden(TaskView tv) {
-        // Unset the saved scroll
-        mLastInfoPaneStackScroll = -1;
-    }
-
-    @Override
     public void onTaskAppInfoClicked(TaskView tv) {
         if (mCb != null) {
             mCb.onTaskAppInfoLaunched(tv.getTask());
@@ -1126,12 +1114,9 @@
     public void onClick(View v) {
         TaskView tv = (TaskView) v;
         Task task = tv.getTask();
-        Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
-                task + " cb: " + mCb);
-
-        // Close any open info panes if the user taps on another task
-        if (closeOpenInfoPanes()) {
-            return;
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
+                    task + " cb: " + mCb);
         }
 
         if (mCb != null) {
@@ -1139,42 +1124,6 @@
         }
     }
 
-    @Override
-    public boolean onLongClick(View v) {
-        if (!Constants.DebugFlags.App.EnableInfoPane) return false;
-
-        TaskView tv = (TaskView) v;
-
-        // Close any other task info panels if we launch another info pane
-        closeOpenInfoPanes();
-
-        // Scroll the task view so that it is maximally visible
-        float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
-        int taskIndex = mStack.indexOfTask(tv.getTask());
-        int curScroll = getStackScroll();
-        int newScroll = (int) Math.max(mMinScroll, Math.min(mMaxScroll, taskIndex * overlapHeight));
-        TaskViewTransform transform = getStackTransform(taskIndex, curScroll);
-        Rect nonOverlapRect = new Rect(transform.rect);
-        if (taskIndex < (mStack.getTaskCount() - 1)) {
-            nonOverlapRect.bottom = nonOverlapRect.top + (int) overlapHeight;
-        }
-
-        // XXX: Use HW Layers
-        if (transform.t < 0f) {
-            animateScroll(curScroll, newScroll, null);
-        } else if (nonOverlapRect.bottom > mStackRectSansPeek.bottom) {
-            // Check if we are out of bounds, if so, just scroll it in such that the bottom of the
-            // task view is visible
-            newScroll = curScroll - (mStackRectSansPeek.bottom - nonOverlapRect.bottom);
-            animateScroll(curScroll, newScroll, null);
-        }
-        mLastInfoPaneStackScroll = newScroll;
-
-        // Show the info pane for this task view
-        tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
-        return true;
-    }
-
     /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
 
     @Override
@@ -1278,9 +1227,11 @@
 
     /** Touch preprocessing for handling below */
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        Console.log(Constants.Log.UI.TouchEvents,
-                "[TaskStackViewTouchHandler|interceptTouchEvent]",
-                Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.TouchEvents,
+                    "[TaskStackViewTouchHandler|interceptTouchEvent]",
+                    Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        }
 
         // Return early if we have no children
         boolean hasChildren = (mSv.getChildCount() > 0);
@@ -1362,9 +1313,11 @@
 
     /** Handles touch events once we have intercepted them */
     public boolean onTouchEvent(MotionEvent ev) {
-        Console.log(Constants.Log.UI.TouchEvents,
-                "[TaskStackViewTouchHandler|touchEvent]",
-                Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.TouchEvents,
+                    "[TaskStackViewTouchHandler|touchEvent]",
+                    Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        }
 
         // Short circuit if we have no children
         boolean hasChildren = (mSv.getChildCount() > 0);
@@ -1465,12 +1418,14 @@
                             Math.abs((float) velocity / mMaximumVelocity)) *
                             Constants.Values.TaskStackView.TaskStackOverscrollRange);
 
-                    Console.log(Constants.Log.UI.TouchEvents,
-                            "[TaskStackViewTouchHandler|fling]",
-                            "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
-                                    " maxVelocity: " + mMaximumVelocity +
-                                    " overscrollRange: " + overscrollRange,
-                            Console.AnsiGreen);
+                    if (Console.Enabled) {
+                        Console.log(Constants.Log.UI.TouchEvents,
+                                "[TaskStackViewTouchHandler|fling]",
+                                "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
+                                        " maxVelocity: " + mMaximumVelocity +
+                                        " overscrollRange: " + overscrollRange,
+                                Console.AnsiGreen);
+                    }
 
                     // Fling scroll
                     mSv.mScroller.fling(0, mSv.getStackScroll(),
@@ -1550,13 +1505,6 @@
         if (parent != null) {
             parent.requestDisallowInterceptTouchEvent(true);
         }
-        // If the info panel is currently showing on this view, then we need to dismiss it
-        if (Constants.DebugFlags.App.EnableInfoPane) {
-            TaskView tv = (TaskView) v;
-            if (tv.isInfoPaneVisible()) {
-                tv.hideInfoPane();
-            }
-        }
     }
 
     @Override
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 46af4c1..16a3f45 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -44,8 +44,6 @@
     /** The TaskView callbacks */
     interface TaskViewCallbacks {
         public void onTaskIconClicked(TaskView tv);
-        public void onTaskInfoPanelShown(TaskView tv);
-        public void onTaskInfoPanelHidden(TaskView tv);
         public void onTaskAppInfoClicked(TaskView tv);
         public void onTaskDismissed(TaskView tv);
 
@@ -58,14 +56,12 @@
 
     Task mTask;
     boolean mTaskDataLoaded;
-    boolean mTaskInfoPaneVisible;
     boolean mIsFocused;
     Point mLastTouchDown = new Point();
     Path mRoundedRectClipPath = new Path();
 
     TaskThumbnailView mThumbnailView;
     TaskBarView mBarView;
-    TaskInfoView mInfoView;
     TaskViewCallbacks mCb;
 
 
@@ -94,7 +90,6 @@
         // Bind the views
         mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
         mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
-        mInfoView = (TaskInfoView) findViewById(R.id.task_view_info_pane);
 
         if (mTaskDataLoaded) {
             onTaskDataLoaded(false);
@@ -280,63 +275,6 @@
         return outRect;
     }
 
-    /** Returns whether this task has an info pane visible */
-    boolean isInfoPaneVisible() {
-        return mTaskInfoPaneVisible;
-    }
-
-    /** Shows the info pane if it is not visible. */
-    void showInfoPane(Rect taskVisibleRect) {
-        if (mTaskInfoPaneVisible) return;
-
-        // Remove the bar view from the visible rect and update the info pane contents
-        taskVisibleRect.top += mBarView.getMeasuredHeight();
-        mInfoView.updateContents(taskVisibleRect);
-
-        // Show the info pane and animate it into view
-        mInfoView.setVisibility(View.VISIBLE);
-        mInfoView.animateCircularClip(mLastTouchDown, 0f, 1f, null, true);
-        mInfoView.setOnClickListener(this);
-        mTaskInfoPaneVisible = true;
-
-        // Notify any callbacks
-        if (mCb != null) {
-            mCb.onTaskInfoPanelShown(this);
-        }
-    }
-
-    /** Hides the info pane if it is visible. */
-    void hideInfoPane() {
-        if (!mTaskInfoPaneVisible) return;
-        RecentsConfiguration config = RecentsConfiguration.getInstance();
-
-        // Cancel any circular clip animation
-        mInfoView.cancelCircularClipAnimation();
-
-        // Animate the info pane out
-        mInfoView.animate()
-                .alpha(0f)
-                .setDuration(config.taskViewInfoPaneAnimDuration)
-                .setInterpolator(config.defaultBezierInterpolator)
-                .withLayer()
-                .withEndAction(new Runnable() {
-                    @Override
-                    public void run() {
-                        mInfoView.setVisibility(View.INVISIBLE);
-                        mInfoView.setOnClickListener(null);
-
-                        mInfoView.setAlpha(1f);
-                    }
-                })
-                .start();
-        mTaskInfoPaneVisible = false;
-
-        // Notify any callbacks
-        if (mCb != null) {
-            mCb.onTaskInfoPanelHidden(this);
-        }
-    }
-
     /** Enable the hw layers on this task view */
     void enableHwLayers() {
         mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -354,7 +292,6 @@
         float dim = (1f - getScaleX()) / scaleRange;
         dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
         mDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
-        invalidate();
     }
 
     @Override
@@ -408,11 +345,10 @@
 
     @Override
     public void onTaskDataLoaded(boolean reloadingTaskData) {
-        if (mThumbnailView != null && mBarView != null && mInfoView != null) {
+        if (mThumbnailView != null && mBarView != null) {
             // Bind each of the views to the new task data
             mThumbnailView.rebindToTask(mTask, reloadingTaskData);
             mBarView.rebindToTask(mTask, reloadingTaskData);
-            mInfoView.rebindToTask(mTask, reloadingTaskData);
             // Rebind any listeners
             mBarView.mApplicationIcon.setOnClickListener(this);
             mBarView.mDismissButton.setOnClickListener(this);
@@ -424,16 +360,13 @@
                     mBarView.mApplicationIcon.setOnLongClickListener(this);
                 }
             }
-            if (Constants.DebugFlags.App.EnableInfoPane) {
-                mInfoView.mAppInfoButton.setOnClickListener(this);
-            }
         }
         mTaskDataLoaded = true;
     }
 
     @Override
     public void onTaskDataUnloaded() {
-        if (mThumbnailView != null && mBarView != null && mInfoView != null) {
+        if (mThumbnailView != null && mBarView != null) {
             // Unbind each of the views from the task data and remove the task callback
             mTask.setCallbacks(null);
             mThumbnailView.unbindFromTask();
@@ -444,18 +377,13 @@
             if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
                 mBarView.mApplicationIcon.setOnLongClickListener(null);
             }
-            if (Constants.DebugFlags.App.EnableInfoPane) {
-                mInfoView.mAppInfoButton.setOnClickListener(null);
-            }
         }
         mTaskDataLoaded = false;
     }
 
     @Override
     public void onClick(View v) {
-        if (v == mInfoView) {
-            hideInfoPane();
-        } else if (v == mBarView.mApplicationIcon) {
+        if (v == mBarView.mApplicationIcon) {
             mCb.onTaskIconClicked(this);
         } else if (v == mBarView.mDismissButton) {
             // Animate out the view and call the callback
@@ -466,8 +394,6 @@
                     mCb.onTaskDismissed(tv);
                 }
             });
-        } else if (v == mInfoView.mAppInfoButton) {
-            mCb.onTaskAppInfoClicked(this);
         }
     }
 
@@ -479,4 +405,4 @@
         }
         return false;
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 724b6a4..ac16164 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -89,7 +89,7 @@
         super.onFinishInflate();
         mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
         mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
-        updateBackgroundResource();
+        updateBackgroundResources();
     }
 
     private final Runnable mTapTimeoutRunnable = new Runnable() {
@@ -215,9 +215,9 @@
         if (mDimmed != dimmed) {
             mDimmed = dimmed;
             if (fade) {
-                fadeBackgroundResource();
+                fadeBackground();
             } else {
-                updateBackgroundResource();
+                updateBackground();
             }
         }
     }
@@ -233,14 +233,14 @@
         mBgTint = bgTint;
         mDimmedBgResId = dimmedBgResId;
         mDimmedBgTint = dimmedTint;
-        updateBackgroundResource();
+        updateBackgroundResources();
     }
 
     public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
         setBackgroundResourceIds(bgResId, 0, dimmedBgResId, 0);
     }
 
-    private void fadeBackgroundResource() {
+    private void fadeBackground() {
         if (mDimmed) {
             mBackgroundDimmed.setVisibility(View.VISIBLE);
         } else {
@@ -256,7 +256,7 @@
             mBackgroundAnimator.removeAllListeners();
             mBackgroundAnimator.cancel();
             if (duration <= 0) {
-                updateBackgroundResource();
+                updateBackground();
                 return;
             }
         }
@@ -279,19 +279,22 @@
         mBackgroundAnimator.start();
     }
 
-    private void updateBackgroundResource() {
+    private void updateBackground() {
         if (mDimmed) {
             mBackgroundDimmed.setVisibility(View.VISIBLE);
-            mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint);
             mBackgroundNormal.setVisibility(View.INVISIBLE);
         } else {
             mBackgroundDimmed.setVisibility(View.INVISIBLE);
             mBackgroundNormal.setVisibility(View.VISIBLE);
-            mBackgroundNormal.setCustomBackground(mBgResId, mBgTint);
             mBackgroundNormal.setAlpha(1f);
         }
     }
 
+    private void updateBackgroundResources() {
+        mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint);
+        mBackgroundNormal.setCustomBackground(mBgResId, mBgTint);
+    }
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index eb4e77a..e699dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -619,7 +619,6 @@
 
     protected void hideRecents(boolean triggeredFromAltTab) {
         if (mRecents != null) {
-            sendCloseSystemWindows(mContext, SYSTEM_DIALOG_REASON_RECENT_APPS);
             mRecents.hideRecents(triggeredFromAltTab);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 0d3116f..eaaac10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -90,9 +90,8 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         if (!mActualHeightInitialized && mActualHeight == 0) {
-            mActualHeight = getInitialHeight();
+            setActualHeight(getInitialHeight());
         }
-        mActualHeightInitialized = true;
     }
 
     protected int getInitialHeight() {
@@ -127,6 +126,7 @@
     }
 
     public void setActualHeight(int actualHeight) {
+        mActualHeightInitialized = true;
         setActualHeight(actualHeight, true);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index e49ec64..3c080fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -31,7 +31,6 @@
     private Drawable mBackground;
     private int mClipTopAmount;
     private int mActualHeight;
-    private boolean mActualHeightInitialized;
 
     public NotificationBackgroundView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -39,15 +38,6 @@
     }
 
     @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        if (!mActualHeightInitialized && mActualHeight == 0) {
-            mActualHeight = getHeight();
-        }
-        mActualHeightInitialized = true;
-    }
-
-    @Override
     protected void onDraw(Canvas canvas) {
         draw(canvas, mBackground);
     }
diff --git a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
index 5602206..a4c2ddd 100644
--- a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
+++ b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
@@ -115,13 +115,14 @@
         }
     }
 
-    public void immersiveModeChanged(String pkg, boolean isImmersiveMode) {
+    public void immersiveModeChanged(String pkg, boolean isImmersiveMode,
+            boolean userSetupComplete) {
         mHandler.removeMessages(H.SHOW);
         if (isImmersiveMode) {
             final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg);
             if (DEBUG) Slog.d(TAG, String.format("immersiveModeChanged() disabled=%s mConfirmed=%s",
                     disabled, mConfirmed));
-            if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed)) {
+            if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed) && userSetupComplete) {
                 mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
             }
         } else {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 6390a69..99dd2f4 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -141,6 +141,11 @@
     // Whether to use the new Session APIs
     static final boolean USE_SESSIONS = true;
 
+    static final int SHORT_PRESS_POWER_NOTHING = 0;
+    static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1;
+    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
+    static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
+
     static final int LONG_PRESS_POWER_NOTHING = 0;
     static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
     static final int LONG_PRESS_POWER_SHUT_OFF = 2;
@@ -298,6 +303,7 @@
     int mLidKeyboardAccessibility;
     int mLidNavigationAccessibility;
     boolean mLidControlsSleep;
+    int mShortPressOnPowerBehavior = -1;
     int mLongPressOnPowerBehavior = -1;
     boolean mScreenOnEarly = false;
     boolean mScreenOnFully = false;
@@ -715,6 +721,33 @@
         mHandler.removeCallbacks(mScreenshotRunnable);
     }
 
+    private void powerShortPress(long eventTime) {
+        if (mShortPressOnPowerBehavior < 0) {
+            mShortPressOnPowerBehavior = mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_shortPressOnPowerBehavior);
+        }
+
+        switch (mShortPressOnPowerBehavior) {
+            case SHORT_PRESS_POWER_NOTHING:
+                break;
+            case SHORT_PRESS_POWER_GO_TO_SLEEP:
+                mPowerManager.goToSleep(eventTime,
+                        PowerManager.GO_TO_SLEEP_REASON_USER, 0);
+                break;
+            case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
+                mPowerManager.goToSleep(eventTime,
+                        PowerManager.GO_TO_SLEEP_REASON_USER,
+                        PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+                break;
+            case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
+                mPowerManager.goToSleep(eventTime,
+                        PowerManager.GO_TO_SLEEP_REASON_USER,
+                        PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+                launchHomeFromHotKey();
+                break;
+        }
+    }
+
     private final Runnable mPowerLongPress = new Runnable() {
         @Override
         public void run() {
@@ -775,6 +808,11 @@
                 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
     }
 
+    boolean isUserSetupComplete() {
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+    }
+
     private void handleLongPressOnHome() {
         if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
             mHomeConsumed = true;
@@ -4033,7 +4071,7 @@
                     mPowerKeyTriggered = false;
                     cancelPendingScreenshotChordAction();
                     if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
-                        mPowerManager.goToSleep(event.getEventTime());
+                        powerShortPress(event.getEventTime());
                         isWakeKey = false;
                     }
                     mPendingPowerKeyUpCanceled = false;
@@ -4294,6 +4332,10 @@
 
     private void requestTransientBars(WindowState swipeTarget) {
         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
+            if (!isUserSetupComplete()) {
+                // Swipe-up for navigation bar is disabled during setup
+                return;
+            }
             boolean sb = mStatusBarController.checkShowTransientBarLw();
             boolean nb = mNavigationBarController.checkShowTransientBarLw();
             if (sb || nb) {
@@ -4921,7 +4963,9 @@
 
     private void applyLidSwitchState() {
         if (mLidState == LID_CLOSED && mLidControlsSleep) {
-            mPowerManager.goToSleep(SystemClock.uptimeMillis());
+            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
+                    PowerManager.GO_TO_SLEEP_REASON_USER,
+                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
         }
     }
 
@@ -5270,7 +5314,8 @@
         boolean newImmersiveMode = isImmersiveMode(vis);
         if (win != null && oldImmersiveMode != newImmersiveMode) {
             final String pkg = win.getOwningPackage();
-            mImmersiveModeConfirmation.immersiveModeChanged(pkg, newImmersiveMode);
+            mImmersiveModeConfirmation.immersiveModeChanged(pkg, newImmersiveMode,
+                    isUserSetupComplete());
         }
 
         vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
@@ -5399,9 +5444,10 @@
                 pw.print(mLidKeyboardAccessibility);
                 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
                 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
-        pw.print(prefix); pw.print("mLongPressOnPowerBehavior=");
-                pw.print(mLongPressOnPowerBehavior);
-                pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
+        pw.print(prefix);
+                pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
+                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
+        pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
         pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
                 pw.print(" mScreenOnFully="); pw.print(mScreenOnFully);
                 pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled);
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index a62d1fd..2222d2c 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -73,14 +73,14 @@
      * latency over peak performance. This is a hint and may have no effect
      * on some implementations.
     */
-    public static final long CREATE_FLAG_LOW_LATENCY = 0x0001;
+    public static final long CREATE_FLAG_LOW_LATENCY = 0x0002;
 
     /*
      * Context creation flag which specifies a context optimized for long
      * battery life over peak performance. This is a hint and may have no effect
      * on some implementations.
     */
-    public static final long CREATE_FLAG_LOW_POWER = 0x0002;
+    public static final long CREATE_FLAG_LOW_POWER = 0x0004;
 
     static {
         sInitialized = false;
@@ -1180,10 +1180,14 @@
             return null;
         }
 
+        if ((flags & ~(CREATE_FLAG_LOW_LATENCY | CREATE_FLAG_LOW_POWER)) != 0) {
+            throw new RSIllegalArgumentException("Invalid flags passed.");
+        }
+
         RenderScript rs = new RenderScript(ctx);
 
         rs.mDev = rs.nDeviceCreate();
-        rs.mContext = rs.nContextCreate(rs.mDev, 0, sdkVersion, ct.mID);
+        rs.mContext = rs.nContextCreate(rs.mDev, (int)flags, sdkVersion, ct.mID);
         rs.mContextType = ct;
         if (rs.mContext == 0) {
             throw new RSDriverException("Failed to create RS context.");
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 168742f..4ab8a01 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -22,7 +22,6 @@
 import android.app.IAlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -40,7 +39,6 @@
 import android.os.WorkSource;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -104,13 +102,21 @@
     int mBroadcastRefCount = 0;
     PowerManager.WakeLock mWakeLock;
     boolean mLastWakeLockUnimportantForLogging;
+    ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<Alarm>();
     ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
     final AlarmHandler mHandler = new AlarmHandler();
     ClockReceiver mClockReceiver;
+    InteractiveStateReceiver mInteractiveStateReceiver;
     private UninstallReceiver mUninstallReceiver;
     final ResultReceiver mResultReceiver = new ResultReceiver();
     PendingIntent mTimeTickSender;
     PendingIntent mDateChangeSender;
+    boolean mInteractive = true;
+    long mNonInteractiveStartTime;
+    long mNonInteractiveTime;
+    long mLastAlarmDeliveryTime;
+    long mStartCurrentDelayTime;
+    long mNextNonWakeupDeliveryTime;
 
     class WakeupEvent {
         public long when;
@@ -318,7 +324,11 @@
     final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
         @Override
         public int compare(Alarm lhs, Alarm rhs) {
-            if (lhs.wakeup != rhs.wakeup) {
+            if ((!lhs.operation.getCreatorPackage().equals(rhs.operation.getCreatorPackage()))
+                    && lhs.wakeup != rhs.wakeup) {
+                // We want to put wakeup alarms before non-wakeup alarms, since they are
+                // the things that drive most activity in the alarm manager.  However,
+                // alarms from the same package should always be ordered strictly by time.
                 return lhs.wakeup ? -1 : 1;
             }
             if (lhs.whenElapsed < rhs.whenElapsed) {
@@ -424,24 +434,21 @@
     static final class InFlight extends Intent {
         final PendingIntent mPendingIntent;
         final WorkSource mWorkSource;
-        final Pair<String, ComponentName> mTarget;
+        final String mTag;
         final BroadcastStats mBroadcastStats;
         final FilterStats mFilterStats;
         final int mAlarmType;
 
         InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
-                int alarmType) {
+                int alarmType, String tag) {
             mPendingIntent = pendingIntent;
             mWorkSource = workSource;
-            Intent intent = pendingIntent.getIntent();
-            mTarget = intent != null
-                    ? new Pair<String, ComponentName>(intent.getAction(), intent.getComponent())
-                    : null;
+            mTag = tag;
             mBroadcastStats = service.getStatsLocked(pendingIntent);
-            FilterStats fs = mBroadcastStats.filterStats.get(mTarget);
+            FilterStats fs = mBroadcastStats.filterStats.get(mTag);
             if (fs == null) {
-                fs = new FilterStats(mBroadcastStats, mTarget);
-                mBroadcastStats.filterStats.put(mTarget, fs);
+                fs = new FilterStats(mBroadcastStats, mTag);
+                mBroadcastStats.filterStats.put(mTag, fs);
             }
             mFilterStats = fs;
             mAlarmType = alarmType;
@@ -450,7 +457,7 @@
 
     static final class FilterStats {
         final BroadcastStats mBroadcastStats;
-        final Pair<String, ComponentName> mTarget;
+        final String mTag;
 
         long aggregateTime;
         int count;
@@ -458,9 +465,9 @@
         long startTime;
         int nesting;
 
-        FilterStats(BroadcastStats broadcastStats, Pair<String, ComponentName> target) {
+        FilterStats(BroadcastStats broadcastStats, String tag) {
             mBroadcastStats = broadcastStats;
-            mTarget = target;
+            mTag = tag;
         }
     }
     
@@ -473,8 +480,7 @@
         int numWakeup;
         long startTime;
         int nesting;
-        final ArrayMap<Pair<String, ComponentName>, FilterStats> filterStats
-                = new ArrayMap<Pair<String, ComponentName>, FilterStats>();
+        final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
 
         BroadcastStats(int uid, String packageName) {
             mUid = uid;
@@ -484,7 +490,11 @@
     
     final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
             = new SparseArray<ArrayMap<String, BroadcastStats>>();
-    
+
+    int mNumDelayedAlarms = 0;
+    long mTotalDelayTime = 0;
+    long mMaxDelayTime = 0;
+
     @Override
     public void onStart() {
         mNativeData = init();
@@ -511,6 +521,7 @@
         mClockReceiver = new ClockReceiver();
         mClockReceiver.scheduleTimeTickEvent();
         mClockReceiver.scheduleDateChangedEvent();
+        mInteractiveStateReceiver = new InteractiveStateReceiver();
         mUninstallReceiver = new UninstallReceiver();
         
         if (mNativeData != 0) {
@@ -735,13 +746,29 @@
 
             pw.print("nowRTC="); pw.print(nowRTC);
             pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
-            pw.print(" nowELAPSED="); pw.println(nowELAPSED);
+            pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
+            pw.println();
+            if (!mInteractive) {
+                pw.print("Time since non-interactive: ");
+                TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
+                pw.println();
+                pw.print("Max wakeup delay: ");
+                TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
+                pw.println();
+                pw.print("Time since last dispatch: ");
+                TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
+                pw.println();
+                pw.print("Next non-wakeup delivery time: ");
+                TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
+                pw.println();
+            }
 
             long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
             long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
-            pw.print("Next alarm: "); pw.print(mNextNonWakeup);
+            pw.print("Next non-wakeup alarm: ");
+                    TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
                     pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
-            pw.print("Next wakeup: "); pw.print(mNextWakeup);
+            pw.print("Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
                     pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
 
             if (mAlarmBatches.size() > 0) {
@@ -750,11 +777,27 @@
                 pw.println(mAlarmBatches.size());
                 for (Batch b : mAlarmBatches) {
                     pw.print(b); pw.println(':');
-                    dumpAlarmList(pw, b.alarms, "  ", nowELAPSED, nowRTC);
+                    dumpAlarmList(pw, b.alarms, "  ", nowELAPSED, nowRTC, sdf);
                 }
             }
 
             pw.println();
+            pw.print("Past-due non-wakeup alarms: ");
+            if (mPendingNonWakeupAlarms.size() > 0) {
+                pw.println(mPendingNonWakeupAlarms.size());
+                dumpAlarmList(pw, mPendingNonWakeupAlarms, "  ", nowELAPSED, nowRTC, sdf);
+            } else {
+                pw.println("(none)");
+            }
+            pw.print("  Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
+            pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
+            pw.println();
+            pw.print("  Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
+            pw.print(", max non-interactive time: ");
+            TimeUtils.formatDuration(mNonInteractiveTime, pw);
+            pw.println();
+
+            pw.println();
             pw.print("  Broadcast ref count: "); pw.println(mBroadcastRefCount);
             pw.println();
 
@@ -811,13 +854,7 @@
                     pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
                     pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
                     pw.println();
-                    pw.print("      ");
-                    if (fs.mTarget.first != null) {
-                        pw.print(" act="); pw.print(fs.mTarget.first);
-                    }
-                    if (fs.mTarget.second != null) {
-                        pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
-                    }
+                    pw.print("      "); pw.print(fs.mTag);
                     pw.println();
                 }
             }
@@ -849,13 +886,8 @@
                                 TimeUtils.formatDuration(fs.aggregateTime, pw);
                                 pw.print(" "); pw.print(fs.numWakeup);
                                 pw.print(" wakes " ); pw.print(fs.count);
-                                pw.print(" alarms:");
-                                if (fs.mTarget.first != null) {
-                                    pw.print(" act="); pw.print(fs.mTarget.first);
-                                }
-                                if (fs.mTarget.second != null) {
-                                    pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
-                                }
+                                pw.print(" alarms: ");
+                                pw.print(fs.mTag);
                                 pw.println();
                     }
                 }
@@ -883,7 +915,7 @@
         }
     }
 
-    private void logBatchesLocked() {
+    private void logBatchesLocked(SimpleDateFormat sdf) {
         ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
         PrintWriter pw = new PrintWriter(bs);
         final long nowRTC = System.currentTimeMillis();
@@ -892,7 +924,7 @@
         for (int iz = 0; iz < NZ; iz++) {
             Batch bz = mAlarmBatches.get(iz);
             pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
-            dumpAlarmList(pw, bz.alarms, "  ", nowELAPSED, nowRTC);
+            dumpAlarmList(pw, bz.alarms, "  ", nowELAPSED, nowRTC, sdf);
             pw.flush();
             Slog.v(TAG, bs.toString());
             bs.reset();
@@ -910,7 +942,8 @@
                     lastTime = b.start;
                 } else {
                     Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
-                    logBatchesLocked();
+                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                    logBatchesLocked(sdf);
                     return false;
                 }
             }
@@ -932,6 +965,7 @@
     void rescheduleKernelAlarmsLocked() {
         // Schedule the next upcoming wakeup alarm.  If there is a deliverable batch
         // prior to that which contains no wakeups, we schedule that as well.
+        long nextNonWakeup = 0;
         if (mAlarmBatches.size() > 0) {
             final Batch firstWakeup = findFirstWakeupBatchLocked();
             final Batch firstBatch = mAlarmBatches.get(0);
@@ -939,11 +973,19 @@
                 mNextWakeup = firstWakeup.start;
                 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
             }
-            if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
-                mNextNonWakeup = firstBatch.start;
-                setLocked(ELAPSED_REALTIME, firstBatch.start);
+            if (firstBatch != firstWakeup) {
+                nextNonWakeup = firstBatch.start;
             }
         }
+        if (mPendingNonWakeupAlarms.size() > 0) {
+            if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
+                nextNonWakeup = mNextNonWakeupDeliveryTime;
+            }
+        }
+        if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
+            mNextNonWakeup = nextNonWakeup;
+            setLocked(ELAPSED_REALTIME, nextNonWakeup);
+        }
     }
 
     private void removeLocked(PendingIntent operation) {
@@ -1003,6 +1045,32 @@
         }
     }
 
+    void interactiveStateChangedLocked(boolean interactive) {
+        if (mInteractive != interactive) {
+            mInteractive = interactive;
+            final long nowELAPSED = SystemClock.elapsedRealtime();
+            if (interactive) {
+                if (mPendingNonWakeupAlarms.size() > 0) {
+                    final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
+                    mTotalDelayTime += thisDelayTime;
+                    if (mMaxDelayTime < thisDelayTime) {
+                        mMaxDelayTime = thisDelayTime;
+                    }
+                    deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
+                    mPendingNonWakeupAlarms.clear();
+                }
+                if (mNonInteractiveStartTime > 0) {
+                    long dur = nowELAPSED - mNonInteractiveStartTime;
+                    if (dur > mNonInteractiveTime) {
+                        mNonInteractiveTime = dur;
+                    }
+                }
+            } else {
+                mNonInteractiveStartTime = nowELAPSED;
+            }
+        }
+    }
+
     boolean lookForPackageLocked(String packageName) {
         for (int i = 0; i < mAlarmBatches.size(); i++) {
             Batch b = mAlarmBatches.get(i);
@@ -1037,12 +1105,12 @@
     }
 
     private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
-            String prefix, String label, long now) {
+            String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
         for (int i=list.size()-1; i>=0; i--) {
             Alarm a = list.get(i);
             pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
                     pw.print(": "); pw.println(a);
-            a.dump(pw, prefix + "  ", now);
+            a.dump(pw, prefix + "  ", nowRTC, nowELAPSED, sdf);
         }
     }
 
@@ -1059,14 +1127,13 @@
     }
 
     private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
-            String prefix, long nowELAPSED, long nowRTC) {
+            String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
         for (int i=list.size()-1; i>=0; i--) {
             Alarm a = list.get(i);
             final String label = labelForType(a.type);
-            long now = (a.type <= RTC) ? nowRTC : nowELAPSED;
             pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
                     pw.print(": "); pw.println(a);
-            a.dump(pw, prefix + "  ", now);
+            a.dump(pw, prefix + "  ", nowRTC, nowELAPSED, sdf);
         }
     }
 
@@ -1077,8 +1144,9 @@
     private native int setKernelTime(long nativeData, long millis);
     private native int setKernelTimezone(long nativeData, int minuteswest);
 
-    void triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
+    boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
             final long nowRTC) {
+        boolean hasWakeup = false;
         // batches are temporally sorted, so we need only pull from the
         // start of the list until we either empty it or hit a batch
         // that is not yet deliverable
@@ -1113,8 +1181,14 @@
                             maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
                             alarm.repeatInterval, alarm.operation, batch.standalone, true,
                             alarm.workSource);
-                }
 
+                    // For now we count this as a wakeup alarm, meaning it needs to be
+                    // delivered immediately.  In the future we should change this, but
+                    // that required delaying when we reschedule the repeat...!
+                    hasWakeup = false;
+                } else if (alarm.wakeup) {
+                    hasWakeup = true;
+                }
             }
         }
 
@@ -1125,6 +1199,8 @@
                 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
             }
         }
+
+        return hasWakeup;
     }
 
     /**
@@ -1147,15 +1223,16 @@
     private static class Alarm {
         public final int type;
         public final boolean wakeup;
+        public final PendingIntent operation;
+        public final String  tag;
+        public final WorkSource workSource;
         public int count;
         public long when;
         public long windowLength;
         public long whenElapsed;    // 'when' in the elapsed time base
         public long maxWhen;        // also in the elapsed time base
         public long repeatInterval;
-        public PendingIntent operation;
-        public WorkSource workSource;
-        
+
         public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
                 long _interval, PendingIntent _op, WorkSource _ws) {
             type = _type;
@@ -1167,12 +1244,17 @@
             maxWhen = _maxWhen;
             repeatInterval = _interval;
             operation = _op;
+            tag = makeTag(_op, _type);
             workSource = _ws;
         }
 
+        public static String makeTag(PendingIntent pi, int type) {
+            return pi.getTag(type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
+                    ? "*walarm*:" : "*alarm*:");
+        }
+
         @Override
-        public String toString()
-        {
+        public String toString() {
             StringBuilder sb = new StringBuilder(128);
             sb.append("Alarm{");
             sb.append(Integer.toHexString(System.identityHashCode(this)));
@@ -1186,11 +1268,20 @@
             return sb.toString();
         }
 
-        public void dump(PrintWriter pw, String prefix, long now) {
+        public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
+                SimpleDateFormat sdf) {
+            final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
+            pw.print(prefix); pw.print("tag="); pw.println(tag);
             pw.print(prefix); pw.print("type="); pw.print(type);
-                    pw.print(" whenElapsed="); pw.print(whenElapsed);
-                    pw.print(" when="); TimeUtils.formatDuration(when, now, pw);
-                    pw.print(" window="); pw.print(windowLength);
+                    pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
+                            nowELAPSED, pw);
+                    if (isRtc) {
+                        pw.print(" when="); pw.print(sdf.format(new Date(when)));
+                    } else {
+                        pw.print(" when="); TimeUtils.formatDuration(when, nowELAPSED, pw);
+                    }
+                    pw.println();
+            pw.print(prefix); pw.print("window="); pw.print(windowLength);
                     pw.print(" repeatInterval="); pw.print(repeatInterval);
                     pw.print(" count="); pw.println(count);
             pw.print(prefix); pw.print("operation="); pw.println(operation);
@@ -1216,6 +1307,102 @@
         }
     }
 
+    long currentNonWakeupFuzzLocked(long nowELAPSED) {
+        long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
+        if (timeSinceOn < 5*60*1000) {
+            // If the screen has been off for 5 minutes, only delay by at most two minutes.
+            return 2*60*1000;
+        } else if (timeSinceOn < 30*60*1000) {
+            // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
+            return 15*60*1000;
+        } else {
+            // Otherwise, we will delay by at most an hour.
+            return 60*60*1000;
+        }
+    }
+
+    boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
+        if (mInteractive) {
+            return false;
+        }
+        if (mLastAlarmDeliveryTime <= 0) {
+            return false;
+        }
+        if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime > nowELAPSED) {
+            // This is just a little paranoia, if somehow we have pending non-wakeup alarms
+            // and the next delivery time is in the past, then just deliver them all.  This
+            // avoids bugs where we get stuck in a loop trying to poll for alarms.
+            return false;
+        }
+        long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
+        return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
+    }
+
+    void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
+        mLastAlarmDeliveryTime = nowELAPSED;
+        for (int i=0; i<triggerList.size(); i++) {
+            Alarm alarm = triggerList.get(i);
+            try {
+                if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
+                alarm.operation.send(getContext(), 0,
+                        mBackgroundIntent.putExtra(
+                                Intent.EXTRA_ALARM_COUNT, alarm.count),
+                        mResultReceiver, mHandler);
+
+                // we have an active broadcast so stay awake.
+                if (mBroadcastRefCount == 0) {
+                    setWakelockWorkSource(alarm.operation, alarm.workSource,
+                            alarm.type, alarm.tag, true);
+                    mWakeLock.acquire();
+                }
+                final InFlight inflight = new InFlight(AlarmManagerService.this,
+                        alarm.operation, alarm.workSource, alarm.type, alarm.tag);
+                mInFlight.add(inflight);
+                mBroadcastRefCount++;
+
+                final BroadcastStats bs = inflight.mBroadcastStats;
+                bs.count++;
+                if (bs.nesting == 0) {
+                    bs.nesting = 1;
+                    bs.startTime = nowELAPSED;
+                } else {
+                    bs.nesting++;
+                }
+                final FilterStats fs = inflight.mFilterStats;
+                fs.count++;
+                if (fs.nesting == 0) {
+                    fs.nesting = 1;
+                    fs.startTime = nowELAPSED;
+                } else {
+                    fs.nesting++;
+                }
+                if (alarm.type == ELAPSED_REALTIME_WAKEUP
+                        || alarm.type == RTC_WAKEUP) {
+                    bs.numWakeup++;
+                    fs.numWakeup++;
+                    if (alarm.workSource != null && alarm.workSource.size() > 0) {
+                        for (int wi=0; wi<alarm.workSource.size(); wi++) {
+                            ActivityManagerNative.noteWakeupAlarm(
+                                    alarm.operation, alarm.workSource.get(wi),
+                                    alarm.workSource.getName(wi));
+                        }
+                    } else {
+                        ActivityManagerNative.noteWakeupAlarm(
+                                alarm.operation, -1, null);
+                    }
+                }
+            } catch (PendingIntent.CanceledException e) {
+                if (alarm.repeatInterval > 0) {
+                    // This IntentSender is no longer valid, but this
+                    // is a repeating alarm, so toss the hoser.
+                    removeImpl(alarm.operation);
+                }
+            } catch (RuntimeException e) {
+                Slog.w(TAG, "Failure sending alarm.", e);
+            }
+        }
+    }
+
     private class AlarmThread extends Thread
     {
         public AlarmThread()
@@ -1269,70 +1456,35 @@
                         }
                     }
 
-                    triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
-                    rescheduleKernelAlarmsLocked();
-
-                    // now deliver the alarm intents
-                    for (int i=0; i<triggerList.size(); i++) {
-                        Alarm alarm = triggerList.get(i);
-                        try {
-                            if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
-                            alarm.operation.send(getContext(), 0,
-                                    mBackgroundIntent.putExtra(
-                                            Intent.EXTRA_ALARM_COUNT, alarm.count),
-                                    mResultReceiver, mHandler);
-                            
-                            // we have an active broadcast so stay awake.
-                            if (mBroadcastRefCount == 0) {
-                                setWakelockWorkSource(alarm.operation, alarm.workSource,
-                                        alarm.type, true);
-                                mWakeLock.acquire();
-                            }
-                            final InFlight inflight = new InFlight(AlarmManagerService.this,
-                                    alarm.operation, alarm.workSource, alarm.type);
-                            mInFlight.add(inflight);
-                            mBroadcastRefCount++;
-
-                            final BroadcastStats bs = inflight.mBroadcastStats;
-                            bs.count++;
-                            if (bs.nesting == 0) {
-                                bs.nesting = 1;
-                                bs.startTime = nowELAPSED;
-                            } else {
-                                bs.nesting++;
-                            }
-                            final FilterStats fs = inflight.mFilterStats;
-                            fs.count++;
-                            if (fs.nesting == 0) {
-                                fs.nesting = 1;
-                                fs.startTime = nowELAPSED;
-                            } else {
-                                fs.nesting++;
-                            }
-                            if (alarm.type == ELAPSED_REALTIME_WAKEUP
-                                    || alarm.type == RTC_WAKEUP) {
-                                bs.numWakeup++;
-                                fs.numWakeup++;
-                                if (alarm.workSource != null && alarm.workSource.size() > 0) {
-                                    for (int wi=0; wi<alarm.workSource.size(); wi++) {
-                                        ActivityManagerNative.noteWakeupAlarm(
-                                                alarm.operation, alarm.workSource.get(wi),
-                                                alarm.workSource.getName(wi));
-                                    }
-                                } else {
-                                    ActivityManagerNative.noteWakeupAlarm(
-                                            alarm.operation, -1, null);
-                                }
-                            }
-                        } catch (PendingIntent.CanceledException e) {
-                            if (alarm.repeatInterval > 0) {
-                                // This IntentSender is no longer valid, but this
-                                // is a repeating alarm, so toss the hoser.
-                                removeImpl(alarm.operation);
-                            }
-                        } catch (RuntimeException e) {
-                            Slog.w(TAG, "Failure sending alarm.", e);
+                    boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
+                    if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
+                        // if there are no wakeup alarms and the screen is off, we can
+                        // delay what we have so far until the future.
+                        if (mPendingNonWakeupAlarms.size() == 0) {
+                            mStartCurrentDelayTime = nowELAPSED;
+                            mNextNonWakeupDeliveryTime = nowELAPSED
+                                    + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
                         }
+                        mPendingNonWakeupAlarms.addAll(triggerList);
+                        mNumDelayedAlarms += triggerList.size();
+                        rescheduleKernelAlarmsLocked();
+                    } else {
+                        // now deliver the alarm intents; if there are pending non-wakeup
+                        // alarms, we need to merge them in to the list.  note we don't
+                        // just deliver them first because we generally want non-wakeup
+                        // alarms delivered after wakeup alarms.
+                        rescheduleKernelAlarmsLocked();
+                        if (mPendingNonWakeupAlarms.size() > 0) {
+                            triggerList.addAll(mPendingNonWakeupAlarms);
+                            Collections.sort(triggerList, mAlarmDispatchComparator);
+                            final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
+                            mTotalDelayTime += thisDelayTime;
+                            if (mMaxDelayTime < thisDelayTime) {
+                                mMaxDelayTime = thisDelayTime;
+                            }
+                            mPendingNonWakeupAlarms.clear();
+                        }
+                        deliverAlarmsLocked(triggerList, nowELAPSED);
                     }
                 }
             }
@@ -1344,14 +1496,13 @@
      * @param pi PendingIntent to attribute blame to if ws is null.
      * @param ws WorkSource to attribute blame.
      */
-    void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, boolean first) {
+    void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
+            boolean first) {
         try {
             final boolean unimportant = pi == mTimeTickSender;
             mWakeLock.setUnimportantForLogging(unimportant);
             if (first || mLastWakeLockUnimportantForLogging) {
-                mWakeLock.setHistoryTag(pi.getTag(
-                        type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
-                                ? "*walarm*:" : "*alarm*:"));
+                mWakeLock.setHistoryTag(tag);
             } else {
                 mWakeLock.setHistoryTag(null);
             }
@@ -1462,6 +1613,23 @@
         }
     }
     
+    class InteractiveStateReceiver extends BroadcastReceiver {
+        public InteractiveStateReceiver() {
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_SCREEN_OFF);
+            filter.addAction(Intent.ACTION_SCREEN_ON);
+            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+            getContext().registerReceiver(this, filter);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            synchronized (mLock) {
+                interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
+            }
+        }
+    }
+
     class UninstallReceiver extends BroadcastReceiver {
         public UninstallReceiver() {
             IntentFilter filter = new IntentFilter();
@@ -1589,7 +1757,7 @@
                     if (mInFlight.size() > 0) {
                         InFlight inFlight = mInFlight.get(0);
                         setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
-                                inFlight.mAlarmType, false);
+                                inFlight.mAlarmType, inFlight.mTag, false);
                     } else {
                         // should never happen
                         mLog.w("Alarm wakelock still held but sent queue empty");
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index cc132be..af53fef0 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -398,7 +398,7 @@
 
     /**
      * used internally when registering NetworkFactories
-     * obj = Messenger
+     * obj = NetworkFactoryInfo
      */
     private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
 
@@ -434,6 +434,13 @@
      */
     private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
 
+    /**
+     * used internally when registering NetworkFactories
+     * obj = Messenger
+     */
+    private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
+
+
     /** Handler used for internal events. */
     final private InternalHandler mHandler;
     /** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -2889,6 +2896,14 @@
             return;
         }
 
+        pw.println("NetworkFactories for:");
+        pw.increaseIndent();
+        for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+            pw.println(nfi.name);
+        }
+        pw.decreaseIndent();
+        pw.println();
+
         NetworkAgentInfo defaultNai = mNetworkForRequestId.get(mDefaultRequest.requestId);
         pw.print("Active default network: ");
         if (defaultNai == null) {
@@ -2983,6 +2998,7 @@
                     if (nai == null) {
                         loge("NetworkAgent not found for EVENT_NETWORK_PROPERTIES_CHANGED");
                     } else {
+                        if (VDBG) log("Update of Linkproperties for " + nai.name());
                         LinkProperties oldLp = nai.linkProperties;
                         nai.linkProperties = (LinkProperties)msg.obj;
                         updateLinkProperties(nai, oldLp);
@@ -3096,18 +3112,19 @@
 
     private void handleAsyncChannelHalfConnect(Message msg) {
         AsyncChannel ac = (AsyncChannel) msg.obj;
-        if (mNetworkFactories.contains(ac)) {
+        if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                 if (VDBG) log("NetworkFactory connected");
                 // A network factory has connected.  Send it all current NetworkRequests.
                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+                    if (nri.isRequest == false) continue;
                     NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
                     ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK,
                             (nai != null ? nai.currentScore : 0), 0, nri.request);
                 }
             } else {
                 loge("Error connecting NetworkFactory");
-                mNetworkFactories.remove(ac);
+                mNetworkFactoryInfos.remove(msg.obj);
             }
         } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
@@ -3214,8 +3231,8 @@
         mNetworkRequests.put(nri.request, nri);
         if (msg.what == EVENT_REGISTER_NETWORK_REQUEST) {
             if (DBG) log("sending new NetworkRequest to factories");
-            for (AsyncChannel ac : mNetworkFactories) {
-                ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
+            for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+                nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
             }
         }
     }
@@ -3236,8 +3253,8 @@
             }
 
             if (nri.isRequest) {
-                for (AsyncChannel factory : mNetworkFactories) {
-                    factory.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
+                for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+                    nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
                 }
 
                 if (affectedNetwork != null) {
@@ -3356,7 +3373,11 @@
                     break;
                 }
                 case EVENT_REGISTER_NETWORK_FACTORY: {
-                    handleRegisterNetworkFactory((Messenger)msg.obj);
+                    handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
+                    break;
+                }
+                case EVENT_UNREGISTER_NETWORK_FACTORY: {
+                    handleUnregisterNetworkFactory((Messenger)msg.obj);
                     break;
                 }
                 case EVENT_REGISTER_NETWORK_AGENT: {
@@ -5222,10 +5243,22 @@
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime, intent);
     }
 
-    private final ArrayList<AsyncChannel> mNetworkFactories = new ArrayList<AsyncChannel>();
+    private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
+            new HashMap<Messenger, NetworkFactoryInfo>();
     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
             new HashMap<NetworkRequest, NetworkRequestInfo>();
 
+    private static class NetworkFactoryInfo {
+        public final String name;
+        public final Messenger messenger;
+        public final AsyncChannel asyncChannel;
+
+        public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
+            this.name = name;
+            this.messenger = messenger;
+            this.asyncChannel = asyncChannel;
+        }
+    }
 
     private class NetworkRequestInfo implements IBinder.DeathRecipient {
         static final boolean REQUEST = true;
@@ -5263,6 +5296,11 @@
                     request + ", " + mBinder + ")");
             releaseNetworkRequest(request);
         }
+
+        public String toString() {
+            return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" +
+                    mPid + " for " + request;
+        }
     }
 
     @Override
@@ -5326,24 +5364,31 @@
     }
 
     @Override
-    public void registerNetworkFactory(Messenger messenger) {
+    public void registerNetworkFactory(Messenger messenger, String name) {
         enforceConnectivityInternalPermission();
-        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, messenger));
+        NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
     }
 
-    private void handleRegisterNetworkFactory(Messenger messenger) {
-        if (VDBG) log("Got NetworkFactory Messenger");
-        AsyncChannel ac = new AsyncChannel();
-        mNetworkFactories.add(ac);
-        ac.connect(mContext, mTrackerHandler, messenger);
-        for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-            if (nri.isRequest) {
-                int score = 0;
-                NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
-                if (currentNetwork != null) score = currentNetwork.currentScore;
-                ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
-            }
+    private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
+        if (VDBG) log("Got NetworkFactory Messenger for " + nfi.name);
+        mNetworkFactoryInfos.put(nfi.messenger, nfi);
+        nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
+    }
+
+    @Override
+    public void unregisterNetworkFactory(Messenger messenger) {
+        enforceConnectivityInternalPermission();
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
+    }
+
+    private void handleUnregisterNetworkFactory(Messenger messenger) {
+        NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
+        if (nfi == null) {
+            if (VDBG) log("Failed to find Messenger in unregisterNetworkFactory");
+            return;
         }
+        if (VDBG) log("unregisterNetworkFactory for " + nfi.name);
     }
 
     /**
@@ -5535,8 +5580,8 @@
 
     private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
         if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
-        for (AsyncChannel ac : mNetworkFactories) {
-            ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
+        for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+            nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
         }
     }
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 50553ee..5cb2a8a6f 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3439,7 +3439,7 @@
                     + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
                     + " mShowForced=" + mShowForced
                     + " mInputShown=" + mInputShown);
-            p.println("  mSystemReady=" + mSystemReady + " mScreenOn=" + mScreenOn);
+            p.println("  mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
         }
 
         p.println(" ");
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 82c13e0..06dd3ed 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -47,6 +47,7 @@
 import com.android.internal.app.IBatteryStats;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.ListIterator;
 
@@ -136,6 +137,10 @@
             }
             return true;
         }
+
+        public boolean isSystemHapticFeedback() {
+            return (mUid == Process.SYSTEM_UID || mUid == 0) && mRepeat < 0;
+        }
     }
 
     VibratorService(Context context) {
@@ -622,20 +627,32 @@
                 }
             }
         }
-    };
+    }
 
     BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
         public void onReceive(Context context, Intent intent) {
             if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                 synchronized (mVibrations) {
-                    doCancelVibrateLocked();
-
-                    int size = mVibrations.size();
-                    for(int i = 0; i < size; i++) {
-                        unlinkVibration(mVibrations.get(i));
+                    // When the system is entering a non-interactive state, we want
+                    // to cancel vibrations in case a misbehaving app has abandoned
+                    // them.  However it may happen that the system is currently playing
+                    // haptic feedback as part of the transition.  So we don't cancel
+                    // system vibrations.
+                    if (mCurrentVibration != null
+                            && !mCurrentVibration.isSystemHapticFeedback()) {
+                        doCancelVibrateLocked();
                     }
 
-                    mVibrations.clear();
+                    // Clear all remaining vibrations.
+                    Iterator<Vibration> it = mVibrations.iterator();
+                    while (it.hasNext()) {
+                        Vibration vibration = it.next();
+                        if (vibration != mCurrentVibration) {
+                            unlinkVibration(vibration);
+                            it.remove();
+                        }
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index c32beda..cd8c13fb 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -264,7 +264,7 @@
             } else if (headset == BIT_USB_HEADSET_DGTL) {
                 device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
             } else if (headset == BIT_HDMI_AUDIO) {
-                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
+                device = AudioManager.DEVICE_OUT_HDMI;
             } else {
                 Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
                 return;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bc264fa..a98c340 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -390,6 +390,7 @@
 
         mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
                 mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
+        mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
 
         // Initialize screen state for battery stats.
         try {
@@ -416,6 +417,13 @@
         }
     };
 
+    private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
+        @Override
+        public void onAnimationEnd() {
+            sendUpdatePowerState();
+        }
+    };
+
     private void updatePowerState() {
         // Update the power state request.
         final boolean mustNotify;
@@ -602,6 +610,7 @@
                 && !mScreenOnWasBlocked
                 && !mElectronBeamOnAnimator.isStarted()
                 && !mElectronBeamOffAnimator.isStarted()
+                && !mScreenBrightnessRampAnimator.isAnimating()
                 && mPowerState.waitUntilClean(mCleanListener)) {
             synchronized (mLock) {
                 if (!mPendingRequestChangedLocked) {
@@ -843,6 +852,9 @@
         pw.println("  mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
         pw.println("  mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
 
+        pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
+                mScreenBrightnessRampAnimator.isAnimating());
+
         if (mElectronBeamOnAnimator != null) {
             pw.println("  mElectronBeamOnAnimator.isStarted()=" +
                     mElectronBeamOnAnimator.isStarted());
diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java
index 6688d6a..ad1e857 100644
--- a/services/core/java/com/android/server/display/RampAnimator.java
+++ b/services/core/java/com/android/server/display/RampAnimator.java
@@ -39,6 +39,8 @@
 
     private boolean mFirstTime = true;
 
+    private Listener mListener;
+
     public RampAnimator(T object, IntProperty<T> property) {
         mObject = object;
         mProperty = property;
@@ -92,6 +94,20 @@
         return changed;
     }
 
+    /**
+     * Returns true if the animation is running.
+     */
+    public boolean isAnimating() {
+        return mAnimating;
+    }
+
+    /**
+     * Sets a listener to watch for animation events.
+     */
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
+
     private void postCallback() {
         mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mCallback, null);
     }
@@ -131,7 +147,14 @@
                 postCallback();
             } else {
                 mAnimating = false;
+                if (mListener != null) {
+                    mListener.onAnimationEnd();
+                }
             }
         }
     };
+
+    public interface Listener {
+        void onAnimationEnd();
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/FeatureAction.java b/services/core/java/com/android/server/hdmi/FeatureAction.java
index d747cd0..1bc278d 100644
--- a/services/core/java/com/android/server/hdmi/FeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/FeatureAction.java
@@ -118,6 +118,11 @@
          * @param delayMillis amount of delay for the timer
          */
         void sendTimerMessage(int state, long delayMillis);
+
+        /**
+         * Removes any pending timer message.
+         */
+        void clearTimerMessage();
     }
 
     private class ActionTimerHandler extends Handler implements ActionTimer {
@@ -132,6 +137,11 @@
         }
 
         @Override
+        public void clearTimerMessage() {
+            removeMessages(MSG_TIMEOUT);
+        }
+
+        @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
             case MSG_TIMEOUT:
@@ -154,15 +164,26 @@
         mActionTimer.sendTimerMessage(state, delayMillis);
     }
 
-    protected final void sendCommand(HdmiCecMessage cmd) {
-        mService.sendCecCommand(cmd);
+    protected final boolean sendCommand(HdmiCecMessage cmd) {
+        return mService.sendCecCommand(cmd);
+    }
+
+    /**
+     * Clean up action's state.
+     *
+     * <p>Declared as package-private. Only {@link HdmiControlService} can access it.
+     */
+    void clear() {
+        mState = STATE_NONE;
+        // Clear all timers.
+        mActionTimer.clearTimerMessage();
     }
 
     /**
      * Finish up the action. Reset the state, and remove itself from the action queue.
      */
     protected void finish() {
-        mState = STATE_NONE;
+        clear();
         removeAction(this);
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 986cb9b..f99a01d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -442,9 +442,9 @@
 
     }
 
-    void sendCommand(HdmiCecMessage cecMessage) {
+    boolean sendCommand(HdmiCecMessage cecMessage) {
         Message message = mIoHandler.obtainMessage(MSG_SEND_CEC_COMMAND, cecMessage);
-        mIoHandler.sendMessage(message);
+        return mIoHandler.sendMessage(message);
     }
 
     /**
@@ -465,7 +465,9 @@
      * Called by native when a hotplug event issues.
      */
     private void handleHotplug(boolean connected) {
-        // TODO: Delegate event to main message handler.
+        // TODO: once add port number to cec HAL interface, pass port number
+        // to the service.
+        mService.onHotplug(0, connected);
     }
 
     private static native long nativeInit(HdmiCecController handler);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index 6d2b83b..e47b90d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -186,6 +186,50 @@
     }
 
     /**
+     * Build &lt;Request Arc Initiation&gt;
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildRequestArcInitiation(int src, int dest) {
+        return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_INITIATION);
+    }
+
+    /**
+     * Build &lt;Request Arc Termination&gt;
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildRequestArcTermination(int src, int dest) {
+        return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_TERMINATION);
+    }
+
+    /**
+     * Build &lt;Report Arc Initiated&gt;
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildReportArcInitiated(int src, int dest) {
+        return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_INITIATED);
+    }
+
+    /**
+     * Build &lt;Report Arc Terminated&gt;
+     *
+     * @param src source address of command
+     * @param dest destination address of command
+     * @return newly created {@link HdmiCecMessage}
+     */
+    static HdmiCecMessage buildReportArcTerminated(int src, int dest) {
+        return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_TERMINATED);
+    }
+
+    /**
      * Build a {@link HdmiCecMessage} without extra parameter.
      *
      * @param src source address of command
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 7c136db..963e818 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -21,12 +21,15 @@
 import android.hardware.hdmi.HdmiCec;
 import android.hardware.hdmi.HdmiCecDeviceInfo;
 import android.hardware.hdmi.HdmiCecMessage;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.util.Slog;
 
 import com.android.server.SystemService;
 
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.Locale;
 
 /**
@@ -41,18 +44,30 @@
     // and sparse call it shares a thread to handle IO operations.
     private final HandlerThread mIoThread = new HandlerThread("Hdmi Control Io Thread");
 
+    // A collection of FeatureAction.
+    // Note that access to this collection should happen in service thread.
+    private final LinkedList<FeatureAction> mActions = new LinkedList<>();
+
     @Nullable
     private HdmiCecController mCecController;
 
     @Nullable
     private HdmiMhlController mMhlController;
 
+    // Whether ARC is "enabled" or not.
+    // TODO: it may need to hold lock if it's accessed from others.
+    private boolean mArcStatusEnabled = false;
+
+    // Handler running on service thread. It's used to run a task in service thread.
+    private Handler mHandler = new Handler();
+
     public HdmiControlService(Context context) {
         super(context);
     }
 
     @Override
     public void onStart() {
+        mIoThread.start();
         mCecController = HdmiCecController.create(this);
         if (mCecController != null) {
             mCecController.initializeLocalDevices(getContext().getResources()
@@ -83,35 +98,83 @@
      * <p>Declared as package-private.
      */
     Looper getServiceLooper() {
-        return Looper.myLooper();
+        return mHandler.getLooper();
     }
 
     /**
-     * Add a new {@link FeatureAction} to the action queue.
+     * Add and start a new {@link FeatureAction} to the action queue.
      *
-     * @param action {@link FeatureAction} to add
+     * @param action {@link FeatureAction} to add and start
      */
-    void addAction(FeatureAction action) {
-        // TODO: Implement this.
+    void addAndStartAction(final FeatureAction action) {
+        // TODO: may need to check the number of stale actions.
+        runOnServiceThread(new Runnable() {
+            @Override
+            public void run() {
+                mActions.add(action);
+                action.start();
+            }
+        });
     }
 
-
     /**
      * Remove the given {@link FeatureAction} object from the action queue.
      *
-     * @param action {@link FeatureAction} to add
+     * @param action {@link FeatureAction} to remove
      */
-    void removeAction(FeatureAction action) {
-        // TODO: Implement this.
+    void removeAction(final FeatureAction action) {
+        runOnServiceThread(new Runnable() {
+            @Override
+            public void run() {
+                mActions.remove(action);
+            }
+        });
+    }
+
+    // Remove all actions matched with the given Class type.
+    private <T extends FeatureAction> void removeAction(final Class<T> clazz) {
+        runOnServiceThread(new Runnable() {
+            @Override
+            public void run() {
+                Iterator<FeatureAction> iter = mActions.iterator();
+                while (iter.hasNext()) {
+                    FeatureAction action = iter.next();
+                    if (action.getClass().equals(clazz)) {
+                        action.clear();
+                        mActions.remove(action);
+                    }
+                }
+            }
+        });
+    }
+
+    private void runOnServiceThread(Runnable runnable) {
+        mHandler.post(runnable);
+    }
+
+    /**
+     * Change ARC status into the given {@code enabled} status.
+     *
+     * @return {@code true} if ARC was in "Enabled" status
+     */
+    boolean setArcStatus(boolean enabled) {
+        boolean oldStatus = mArcStatusEnabled;
+        // 1. Enable/disable ARC circuit.
+        // TODO: call set_audio_return_channel of hal interface.
+
+        // 2. Update arc status;
+        mArcStatusEnabled = enabled;
+        return oldStatus;
     }
 
     /**
      * Transmit a CEC command to CEC bus.
      *
      * @param command CEC command to send out
+     * @return {@code true} if succeeds to send command
      */
-    void sendCecCommand(HdmiCecMessage command) {
-        mCecController.sendCommand(command);
+    boolean sendCecCommand(HdmiCecMessage command) {
+        return mCecController.sendCommand(command);
     }
 
     /**
@@ -142,6 +205,12 @@
             case HdmiCec.MESSAGE_GET_CEC_VERSION:
                 handleGetCecVersion(message);
                 return true;
+            case HdmiCec.MESSAGE_INITIATE_ARC:
+                handleInitiateArc(message);
+                return true;
+            case HdmiCec.MESSAGE_TERMINATE_ARC:
+                handleTerminateArc(message);
+                return true;
             // TODO: Add remaining system information query such as
             // <Give Device Power Status> and <Request Active Source> handler.
             default:
@@ -150,6 +219,36 @@
         }
     }
 
+    /**
+     * Called when a new hotplug event is issued.
+     *
+     * @param port hdmi port number where hot plug event issued.
+     * @param connected whether to be plugged in or not
+     */
+    void onHotplug(int portNo, boolean connected) {
+        // TODO: Start "RequestArcInitiationAction" if ARC port.
+    }
+
+    private void handleInitiateArc(HdmiCecMessage message){
+        // In case where <Initiate Arc> is started by <Request ARC Initiation>
+        // need to clean up RequestArcInitiationAction.
+        removeAction(RequestArcInitiationAction.class);
+        SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this,
+                message.getDestination(), message.getSource(), true);
+        addAndStartAction(action);
+    }
+
+    private void handleTerminateArc(HdmiCecMessage message) {
+        // In case where <Terminate Arc> is started by <Request ARC Termination>
+        // need to clean up RequestArcInitiationAction.
+        // TODO: check conditions of power status by calling is_connected api
+        // to be added soon.
+        removeAction(RequestArcTerminationAction.class);
+        SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this,
+                message.getDestination(), message.getSource(), false);
+        addAndStartAction(action);
+    }
+
     private void handleGetCecVersion(HdmiCecMessage message) {
         int version = mCecController.getVersion();
         HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
index e0bc718..156bbbe 100644
--- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -103,7 +103,7 @@
                 requestVendorId();
                 return true;
             } else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
-                int requestOpcode = params[1];
+                int requestOpcode = params[1] & 0xff;
                 if (requestOpcode == HdmiCec.MESSAGE_SET_OSD_NAME) {
                     mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID;
                     requestVendorId();
@@ -113,7 +113,8 @@
         } else if (mState == STATE_WAITING_FOR_DEVICE_VENDOR_ID) {
             if (opcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) {
                 if (params.length == 3) {
-                    mVendorId = (params[0] << 16) + (params[1] << 8) + params[2];
+                    mVendorId = ((params[0] & 0xff) << 16) + ((params[1] & 0xff) << 8)
+                        + (params[2] & 0xff);
                 } else {
                     Slog.e(TAG, "Failed to get device vendor ID: ");
                 }
@@ -121,7 +122,7 @@
                 finish();
                 return true;
             } else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
-                int requestOpcode = params[1];
+                int requestOpcode = params[1] & 0xff;
                 if (requestOpcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) {
                     addDeviceInfo();
                     finish();
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
new file mode 100644
index 0000000..196f28a
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.util.Slog;
+
+/**
+ * Base feature action class for &lt;Request ARC Initiation&gt;/&lt;Request ARC Termination&gt;.
+ */
+abstract class RequestArcAction extends FeatureAction {
+    private static final String TAG = "RequestArcAction";
+
+    // State in which waits for ARC response.
+    protected static final int STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE = 1;
+
+    // Logical address of AV Receiver.
+    protected final int mAvrAddress;
+
+    /**
+     * @Constructor
+     *
+     * @param service {@link HdmiControlService} instance
+     * @param sourceAddress logical address to be used as source address. It should
+     *                      TV type
+     * @param avrAddress address of AV receiver. It should be AUDIO_SYSTEM type
+     * @throw IllegalArugmentException if device type of sourceAddress and avrAddress
+     *                      is invalid
+     */
+    RequestArcAction(HdmiControlService service, int sourceAddress, int avrAddress) {
+        super(service, sourceAddress);
+        verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
+        verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+        mAvrAddress = avrAddress;
+    }
+
+    private static void verifyAddressType(int logicalAddress, int deviceType) {
+        int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
+        if (actualDeviceType != deviceType) {
+            throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
+                    + ", Actual:" + actualDeviceType);
+        }
+    }
+
+    @Override
+    boolean processCommand(HdmiCecMessage cmd) {
+        if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
+            return false;
+        }
+
+        int src = cmd.getSource();
+        if (src != mAvrAddress) {
+            Slog.w(TAG, "Invalid source [Expected:" + mAvrAddress + ", Actual:" + src + "]");
+            return false;
+        }
+        int opcode = cmd.getOpcode();
+        switch (opcode) {
+            // Handles only <Feature Abort> here and, both <Initiate ARC> and <Terminate ARC>
+            // are handled in HdmiControlService itself because both can be
+            // received wihtout <Request ARC Initiation> or <Request ARC Termination>.
+            case HdmiCec.MESSAGE_FEATURE_ABORT:
+                disableArcTransmission();
+                finish();
+                return true;
+            default:
+                Slog.w(TAG, "Unsupported opcode:" + cmd.toString());
+        }
+        return false;
+    }
+
+    protected final void disableArcTransmission() {
+        // Start Set ARC Transmission State action.
+        SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(mService,
+                mSourceAddress, mAvrAddress, false);
+        mService.addAndStartAction(action);
+    }
+
+    @Override
+    final void handleTimerEvent(int state) {
+        if (mState != state || state != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
+            return;
+        }
+        disableArcTransmission();
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
new file mode 100644
index 0000000..0a701f9
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.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.server.hdmi;
+
+import android.util.Slog;
+
+/**
+ * Feature action that handles ARC action initiated by TV devices.
+ *
+ * <p>This action is created by TV's hot plug event of ARC port.
+ */
+final class RequestArcInitiationAction extends RequestArcAction {
+    private static final String TAG = "RequestArcInitiationAction";
+
+    /**
+     * @Constructor
+     *
+     * For more details look at {@link RequestArcAction#RequestArcAction}.
+     */
+    RequestArcInitiationAction(HdmiControlService service, int sourceAddress, int avrAddress) {
+        super(service, sourceAddress, avrAddress);
+    }
+
+    @Override
+    boolean start() {
+        if (sendCommand(
+                HdmiCecMessageBuilder.buildRequestArcInitiation(mSourceAddress, mAvrAddress))) {
+            mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
+            addTimer(mState, TIMEOUT_MS);
+        } else {
+            Slog.w(TAG, "Failed to send <Request ARC Initiation>");
+            // If failed to send <Request ARC Initiation>, start "Disabled" ARC transmission
+            // action.
+            disableArcTransmission();
+            finish();
+        }
+        return true;
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
new file mode 100644
index 0000000..db1b992
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.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.server.hdmi;
+
+import android.util.Slog;
+
+/**
+ * Feature action to handle <Request ARC Termination>.
+ *
+ * <p>It's initiated by user's manual termination or ARC channel close from TV.
+ */
+final class RequestArcTerminationAction extends RequestArcAction {
+    private static final String TAG = "RequestArcTerminationAction";
+
+    /**
+     * @Constructor
+     *
+     * @see RequestArcAction#RequestArcAction
+     */
+    RequestArcTerminationAction(HdmiControlService service, int sourceAddress, int avrAddress) {
+        super(service, sourceAddress, avrAddress);
+    }
+
+    @Override
+    boolean start() {
+        if (sendCommand(
+                HdmiCecMessageBuilder.buildRequestArcTermination(mSourceAddress, mAvrAddress))) {
+            mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
+            addTimer(mState, TIMEOUT_MS);
+        } else {
+            Slog.w(TAG, "Failed to send <Request ARC Initiation>");
+            // If failed to send <Request ARC Termination>, start "Disabled" ARC transmission
+            // action.
+            disableArcTransmission();
+            finish();
+        }
+        return true;
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
new file mode 100644
index 0000000..6bf149b
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.util.Slog;
+
+/**
+ * Feature action that handles enabling/disabling of ARC transmission channel.
+ * Once TV gets &lt;Initiate ARC&gt;, TV sends &lt;Report ARC Initiated&gt; to AV Receiver.
+ * If it fails or it gets &lt;Terminate ARC&gt;, TV just disables ARC.
+ */
+final class SetArcTransmissionStateAction extends FeatureAction {
+    private static final String TAG = "SetArcTransmissionStateAction";
+
+    // State in which the action sent <Rerpot Arc Initiated> and
+    // is waiting for time out. If it receives <Feature Abort> within timeout
+    // ARC should be disabled.
+    private static final int STATE_WAITING_TIMEOUT = 1;
+
+    private final boolean mEnabled;
+    private final int mAvrAddress;
+
+    /**
+     * @Constructor
+     *
+     * @param service an instance of {@link HdmiControlService}
+     * @param sourceAddress logical address to be used as source address
+     * @param enabled whether to enable ARC Transmission channel
+     */
+    SetArcTransmissionStateAction(HdmiControlService service, int sourceAddress, int avrAddress,
+            boolean enabled) {
+        super(service, sourceAddress);
+        verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
+        verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+        mAvrAddress = avrAddress;
+        mEnabled = enabled;
+    }
+
+    // TODO: extract it as separate utility class.
+    private static void verifyAddressType(int logicalAddress, int deviceType) {
+        int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
+        if (actualDeviceType != deviceType) {
+            throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
+                    + ", Actual:" + actualDeviceType);
+        }
+    }
+
+    @Override
+    boolean start() {
+        if (mEnabled) {
+            if (sendCommand(
+                    HdmiCecMessageBuilder.buildReportArcInitiated(mSourceAddress, mAvrAddress))) {
+                // Enable ARC status immediately after sending <Report Arc Initiated>.
+                // If AVR responds with <Feature Abort>, disable ARC status again.
+                // This is different from spec that says that turns ARC status to "Enabled"
+                // if <Report ARC Initiated> is acknowledged and no <Feature Abort> is received.
+                // But implemented this way to save the time having to wait for <Feature Abort>.
+                setArcStatus(true);
+                // If succeeds to send <Report ARC Initiated>, wait general timeout
+                // to check whether there is no <Feature Abort> for <Report ARC Initiated>.
+                mState = STATE_WAITING_TIMEOUT;
+                addTimer(mState, TIMEOUT_MS);
+            } else {
+                // If fails to send <Report ARC Initiated>, disable ARC and
+                // send <Report ARC Terminated> directly.
+                Slog.w(TAG, "Failed to send <Report ARC Initiated>:[source:" + mSourceAddress
+                        + ", avr Address:" + mAvrAddress + "]");
+                setArcStatus(false);
+                finish();
+            }
+        } else {
+            setArcStatus(false);
+            finish();
+        }
+        return true;
+    }
+
+    private void setArcStatus(boolean enabled) {
+        boolean wasEnabled = mService.setArcStatus(enabled);
+        Slog.i(TAG, "Change arc status [old:" + wasEnabled + " ,new:" + enabled);
+
+        // If enabled before and set to "disabled" and send <Report Arc Terminated> to
+        // av reciever.
+        if (!enabled && wasEnabled) {
+            sendCommand(
+                    HdmiCecMessageBuilder.buildReportArcTerminated(mSourceAddress, mAvrAddress));
+        }
+    }
+
+    @Override
+    boolean processCommand(HdmiCecMessage cmd) {
+        if (mState != STATE_WAITING_TIMEOUT) {
+            return false;
+        }
+
+        int opcode = cmd.getOpcode();
+        if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
+            setArcStatus(false);
+        }
+        finish();
+        return true;
+    }
+
+    @Override
+    void handleTimerEvent(int state) {
+        if (mState != state || mState != STATE_WAITING_TIMEOUT) {
+            return;
+        }
+        // Expire timeout for <Feature Abort>.
+        finish();
+    }
+}
diff --git a/services/core/java/com/android/server/net/DelayedDiskWrite.java b/services/core/java/com/android/server/net/DelayedDiskWrite.java
new file mode 100644
index 0000000..6ed277d
--- /dev/null
+++ b/services/core/java/com/android/server/net/DelayedDiskWrite.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class DelayedDiskWrite {
+    private HandlerThread mDiskWriteHandlerThread;
+    private Handler mDiskWriteHandler;
+    /* Tracks multiple writes on the same thread */
+    private int mWriteSequence = 0;
+    private final String TAG = "DelayedDiskWrite";
+
+    public interface Writer {
+        public void onWriteCalled(DataOutputStream out) throws IOException;
+    }
+
+    public void write(final String filePath, final Writer w) {
+        if (TextUtils.isEmpty(filePath)) {
+            throw new IllegalArgumentException("empty file path");
+        }
+
+        /* Do a delayed write to disk on a separate handler thread */
+        synchronized (this) {
+            if (++mWriteSequence == 1) {
+                mDiskWriteHandlerThread = new HandlerThread("DelayedDiskWriteThread");
+                mDiskWriteHandlerThread.start();
+                mDiskWriteHandler = new Handler(mDiskWriteHandlerThread.getLooper());
+            }
+        }
+
+        mDiskWriteHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                doWrite(filePath, w);
+            }
+        });
+    }
+
+    private void doWrite(String filePath, Writer w) {
+        DataOutputStream out = null;
+        try {
+            out = new DataOutputStream(new BufferedOutputStream(
+                        new FileOutputStream(filePath)));
+            w.onWriteCalled(out);
+        } catch (IOException e) {
+            loge("Error writing data file " + filePath);
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (Exception e) {}
+            }
+
+            // Quit if no more writes sent
+            synchronized (this) {
+                if (--mWriteSequence == 0) {
+                    mDiskWriteHandler.getLooper().quit();
+                    mDiskWriteHandler = null;
+                    mDiskWriteHandlerThread = null;
+                }
+            }
+        }
+    }
+
+    private void loge(String s) {
+        Log.e(TAG, s);
+    }
+}
+
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
new file mode 100644
index 0000000..6ccbec0
--- /dev/null
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net;
+
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.net.ProxyInfo;
+import android.net.RouteInfo;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.server.net.DelayedDiskWrite;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.Map;
+
+public class IpConfigStore {
+    private static final String TAG = "IpConfigStore";
+    private static final boolean DBG = true;
+
+    protected final DelayedDiskWrite mWriter;
+
+    /* IP and proxy configuration keys */
+    protected static final String ID_KEY = "id";
+    protected static final String IP_ASSIGNMENT_KEY = "ipAssignment";
+    protected static final String LINK_ADDRESS_KEY = "linkAddress";
+    protected static final String GATEWAY_KEY = "gateway";
+    protected static final String DNS_KEY = "dns";
+    protected static final String PROXY_SETTINGS_KEY = "proxySettings";
+    protected static final String PROXY_HOST_KEY = "proxyHost";
+    protected static final String PROXY_PORT_KEY = "proxyPort";
+    protected static final String PROXY_PAC_FILE = "proxyPac";
+    protected static final String EXCLUSION_LIST_KEY = "exclusionList";
+    protected static final String EOS = "eos";
+
+    protected static final int IPCONFIG_FILE_VERSION = 2;
+
+    public IpConfigStore() {
+        mWriter = new DelayedDiskWrite();
+    }
+
+    private boolean writeConfig(DataOutputStream out, int configKey,
+                                  IpConfiguration config) throws IOException {
+        boolean written = false;
+
+        try {
+            LinkProperties linkProperties = config.linkProperties;
+            switch (config.ipAssignment) {
+                case STATIC:
+                    out.writeUTF(IP_ASSIGNMENT_KEY);
+                    out.writeUTF(config.ipAssignment.toString());
+                    for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) {
+                        out.writeUTF(LINK_ADDRESS_KEY);
+                        out.writeUTF(linkAddr.getAddress().getHostAddress());
+                        out.writeInt(linkAddr.getNetworkPrefixLength());
+                    }
+                    for (RouteInfo route : linkProperties.getRoutes()) {
+                        out.writeUTF(GATEWAY_KEY);
+                        LinkAddress dest = route.getDestination();
+                        if (dest != null) {
+                            out.writeInt(1);
+                            out.writeUTF(dest.getAddress().getHostAddress());
+                            out.writeInt(dest.getNetworkPrefixLength());
+                        } else {
+                            out.writeInt(0);
+                        }
+                        if (route.getGateway() != null) {
+                            out.writeInt(1);
+                            out.writeUTF(route.getGateway().getHostAddress());
+                        } else {
+                            out.writeInt(0);
+                        }
+                    }
+                    for (InetAddress inetAddr : linkProperties.getDnses()) {
+                        out.writeUTF(DNS_KEY);
+                        out.writeUTF(inetAddr.getHostAddress());
+                    }
+                    written = true;
+                    break;
+                case DHCP:
+                    out.writeUTF(IP_ASSIGNMENT_KEY);
+                    out.writeUTF(config.ipAssignment.toString());
+                    written = true;
+                    break;
+                case UNASSIGNED:
+                /* Ignore */
+                    break;
+                default:
+                    loge("Ignore invalid ip assignment while writing");
+                    break;
+            }
+
+            switch (config.proxySettings) {
+                case STATIC:
+                    ProxyInfo proxyProperties = linkProperties.getHttpProxy();
+                    String exclusionList = proxyProperties.getExclusionListAsString();
+                    out.writeUTF(PROXY_SETTINGS_KEY);
+                    out.writeUTF(config.proxySettings.toString());
+                    out.writeUTF(PROXY_HOST_KEY);
+                    out.writeUTF(proxyProperties.getHost());
+                    out.writeUTF(PROXY_PORT_KEY);
+                    out.writeInt(proxyProperties.getPort());
+                    out.writeUTF(EXCLUSION_LIST_KEY);
+                    out.writeUTF(exclusionList);
+                    written = true;
+                    break;
+                case PAC:
+                    ProxyInfo proxyPacProperties = linkProperties.getHttpProxy();
+                    out.writeUTF(PROXY_SETTINGS_KEY);
+                    out.writeUTF(config.proxySettings.toString());
+                    out.writeUTF(PROXY_PAC_FILE);
+                    out.writeUTF(proxyPacProperties.getPacFileUrl().toString());
+                    written = true;
+                    break;
+                case NONE:
+                    out.writeUTF(PROXY_SETTINGS_KEY);
+                    out.writeUTF(config.proxySettings.toString());
+                    written = true;
+                    break;
+                case UNASSIGNED:
+                    /* Ignore */
+                        break;
+                    default:
+                        loge("Ignore invalid proxy settings while writing");
+                        break;
+            }
+
+            if (written) {
+                out.writeUTF(ID_KEY);
+                out.writeInt(configKey);
+            }
+        } catch (NullPointerException e) {
+            loge("Failure in writing " + config.linkProperties + e);
+        }
+        out.writeUTF(EOS);
+
+        return written;
+    }
+
+    public void writeIpAndProxyConfigurations(String filePath,
+                                              final SparseArray<IpConfiguration> networks) {
+        mWriter.write(filePath, new DelayedDiskWrite.Writer() {
+            public void onWriteCalled(DataOutputStream out) throws IOException{
+                out.writeInt(IPCONFIG_FILE_VERSION);
+                for(int i = 0; i < networks.size(); i++) {
+                    writeConfig(out, networks.keyAt(i), networks.valueAt(i));
+                }
+            }
+        });
+    }
+
+    public SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
+        SparseArray<IpConfiguration> networks = new SparseArray<IpConfiguration>();
+
+        DataInputStream in = null;
+        try {
+            in = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
+
+            int version = in.readInt();
+            if (version != 2 && version != 1) {
+                loge("Bad version on IP configuration file, ignore read");
+                return null;
+            }
+
+            while (true) {
+                int id = -1;
+                // Default is DHCP with no proxy
+                IpAssignment ipAssignment = IpAssignment.DHCP;
+                ProxySettings proxySettings = ProxySettings.NONE;
+                LinkProperties linkProperties = new LinkProperties();
+                String proxyHost = null;
+                String pacFileUrl = null;
+                int proxyPort = -1;
+                String exclusionList = null;
+                String key;
+
+                do {
+                    key = in.readUTF();
+                    try {
+                        if (key.equals(ID_KEY)) {
+                            id = in.readInt();
+                        } else if (key.equals(IP_ASSIGNMENT_KEY)) {
+                            ipAssignment = IpAssignment.valueOf(in.readUTF());
+                        } else if (key.equals(LINK_ADDRESS_KEY)) {
+                            LinkAddress linkAddr = new LinkAddress(
+                                    NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
+                            linkProperties.addLinkAddress(linkAddr);
+                        } else if (key.equals(GATEWAY_KEY)) {
+                            LinkAddress dest = null;
+                            InetAddress gateway = null;
+                            if (version == 1) {
+                                // only supported default gateways - leave the dest/prefix empty
+                                gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                            } else {
+                                if (in.readInt() == 1) {
+                                    dest = new LinkAddress(
+                                            NetworkUtils.numericToInetAddress(in.readUTF()),
+                                            in.readInt());
+                                }
+                                if (in.readInt() == 1) {
+                                    gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                                }
+                            }
+                            linkProperties.addRoute(new RouteInfo(dest, gateway));
+                        } else if (key.equals(DNS_KEY)) {
+                            linkProperties.addDns(
+                                    NetworkUtils.numericToInetAddress(in.readUTF()));
+                        } else if (key.equals(PROXY_SETTINGS_KEY)) {
+                            proxySettings = ProxySettings.valueOf(in.readUTF());
+                        } else if (key.equals(PROXY_HOST_KEY)) {
+                            proxyHost = in.readUTF();
+                        } else if (key.equals(PROXY_PORT_KEY)) {
+                            proxyPort = in.readInt();
+                        } else if (key.equals(PROXY_PAC_FILE)) {
+                            pacFileUrl = in.readUTF();
+                        } else if (key.equals(EXCLUSION_LIST_KEY)) {
+                            exclusionList = in.readUTF();
+                        } else if (key.equals(EOS)) {
+                            break;
+                        } else {
+                            loge("Ignore unknown key " + key + "while reading");
+                        }
+                    } catch (IllegalArgumentException e) {
+                        loge("Ignore invalid address while reading" + e);
+                    }
+                } while (true);
+
+                if (id != -1) {
+                    IpConfiguration config = new IpConfiguration();
+                    networks.put(id, config);
+
+                    config.linkProperties = linkProperties;
+                    switch (ipAssignment) {
+                        case STATIC:
+                        case DHCP:
+                            config.ipAssignment = ipAssignment;
+                            break;
+                        case UNASSIGNED:
+                            loge("BUG: Found UNASSIGNED IP on file, use DHCP");
+                            config.ipAssignment = IpAssignment.DHCP;
+                            break;
+                        default:
+                            loge("Ignore invalid ip assignment while reading.");
+                            config.ipAssignment = IpAssignment.UNASSIGNED;
+                            break;
+                    }
+
+                    switch (proxySettings) {
+                        case STATIC:
+                            config.proxySettings = proxySettings;
+                            ProxyInfo ProxyInfo =
+                                    new ProxyInfo(proxyHost, proxyPort, exclusionList);
+                            linkProperties.setHttpProxy(ProxyInfo);
+                            break;
+                        case PAC:
+                            config.proxySettings = proxySettings;
+                            ProxyInfo proxyPacProperties =
+                                    new ProxyInfo(pacFileUrl);
+                            linkProperties.setHttpProxy(proxyPacProperties);
+                            break;
+                        case NONE:
+                            config.proxySettings = proxySettings;
+                            break;
+                        case UNASSIGNED:
+                            loge("BUG: Found UNASSIGNED proxy on file, use NONE");
+                            config.proxySettings = ProxySettings.NONE;
+                            break;
+                        default:
+                            loge("Ignore invalid proxy settings while reading");
+                            config.proxySettings = ProxySettings.UNASSIGNED;
+                            break;
+                    }
+                } else {
+                    if (DBG) log("Missing id while parsing configuration");
+                }
+            }
+        } catch (EOFException ignore) {
+        } catch (IOException e) {
+            loge("Error parsing configuration" + e);
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (Exception e) {}
+            }
+        }
+
+        return networks;
+    }
+
+    protected void loge(String s) {
+        Log.e(TAG, s);
+    }
+
+    protected void log(String s) {
+        Log.d(TAG, s);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 61b3a89..dd5e9de 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5486,6 +5486,20 @@
         }
         pkg.mScanPath = path;
 
+        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.
+            //
+            // We also do this *before* we perform dexopt on this package, so that
+            // we can avoid redundant dexopts, and also to make sure we've got the
+            // code and package path correct.
+            if (!adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
+                    pkg, forceDex, (scanMode & SCAN_DEFER_DEX) != 0)) {
+                mLastScanError = PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
+                return null;
+            }
+        }
+
         if ((scanMode&SCAN_NO_DEX) == 0) {
             if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
                     == DEX_OPT_FAILED) {
@@ -5613,16 +5627,6 @@
 
         // writer
         synchronized (mPackages) {
-            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.
-                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) {
                 mAppDirs.put(pkg.mPath, pkg);
@@ -5967,19 +5971,43 @@
         return pkg;
     }
 
+    /**
+     * Adjusts ABIs for a set of packages belonging to a shared user so that they all match.
+     * i.e, so that all packages can be run inside a single process if required.
+     *
+     * Optionally, callers can pass in a parsed package via {@code newPackage} in which case
+     * this function will either try and make the ABI for all packages in {@code packagesForUser}
+     * match {@code scannedPackage} or will update the ABI of {@code scannedPackage} to match
+     * the ABI selected for {@code packagesForUser}. This variant is used when installing or
+     * updating a package that belongs to a shared user.
+     */
     private boolean adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
-            String requiredInstructionSet, boolean forceDexOpt, boolean deferDexOpt) {
+            PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt) {
+        String requiredInstructionSet = null;
+        if (scannedPackage != null && scannedPackage.applicationInfo.cpuAbi != null) {
+            requiredInstructionSet = VMRuntime.getInstructionSet(
+                     scannedPackage.applicationInfo.cpuAbi);
+        }
+
         PackageSetting requirer = null;
         for (PackageSetting ps : packagesForUser) {
-            if (ps.cpuAbiString != null) {
+            // If packagesForUser contains scannedPackage, we skip it. This will happen
+            // when scannedPackage is an update of an existing package. Without this check,
+            // we will never be able to change the ABI of any package belonging to a shared
+            // user, even if it's compatible with other packages.
+            if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) {
+                if (ps.cpuAbiString == null) {
+                    continue;
+                }
+
                 final String instructionSet = VMRuntime.getInstructionSet(ps.cpuAbiString);
                 if (requiredInstructionSet != null) {
                     if (!instructionSet.equals(requiredInstructionSet)) {
                         // We have a mismatch between instruction sets (say arm vs arm64).
                         // bail out.
                         String errorMessage = "Instruction set mismatch, "
-                                + ((requirer == null) ? "[caller]" : requirer.pkg)
-                                + " requires " + requiredInstructionSet + " whereas " + ps.pkg
+                                + ((requirer == null) ? "[caller]" : requirer)
+                                + " requires " + requiredInstructionSet + " whereas " + ps
                                 + " requires " + instructionSet;
                         Slog.e(TAG, errorMessage);
 
@@ -5995,20 +6023,37 @@
         }
 
         if (requiredInstructionSet != null) {
-            for (PackageSetting ps : packagesForUser) {
-                if (ps.cpuAbiString == null) {
-                    ps.cpuAbiString = requirer.cpuAbiString;
-                    if (ps.pkg != null) {
-                        ps.pkg.applicationInfo.cpuAbi = requirer.cpuAbiString;
-                        Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.cpuAbiString);
+            String adjustedAbi;
+            if (requirer != null) {
+                // requirer != null implies that either scannedPackage was null or that scannedPackage
+                // did not require an ABI, in which case we have to adjust scannedPackage to match
+                // the ABI of the set (which is the same as requirer's ABI)
+                adjustedAbi = requirer.cpuAbiString;
+                if (scannedPackage != null) {
+                    scannedPackage.applicationInfo.cpuAbi = adjustedAbi;
+                }
+            } else {
+                // requirer == null implies that we're updating all ABIs in the set to
+                // match scannedPackage.
+                adjustedAbi =  scannedPackage.applicationInfo.cpuAbi;
+            }
 
-                        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());
-                        }
+            for (PackageSetting ps : packagesForUser) {
+                if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) {
+                    if (ps.cpuAbiString != null) {
+                        continue;
+                    }
+
+                    ps.cpuAbiString = adjustedAbi;
+                    ps.pkg.applicationInfo.cpuAbi = adjustedAbi;
+                    Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi);
+
+                    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());
                     }
                 }
             }
@@ -11876,6 +11921,7 @@
                 pw.println("  cmd may be one of:");
                 pw.println("    l[ibraries]: list known shared libraries");
                 pw.println("    f[ibraries]: list device features");
+                pw.println("    k[eysets]: print known keysets");
                 pw.println("    r[esolvers]: dump intent resolvers");
                 pw.println("    perm[issions]: dump permissions");
                 pw.println("    pref[erred]: print preferred package settings");
@@ -11886,8 +11932,8 @@
                 pw.println("    m[essages]: print collected runtime messages");
                 pw.println("    v[erifiers]: print package verifier info");
                 pw.println("    version: print database version info");
+                pw.println("    write: write current settings now");
                 pw.println("    <package.name>: info about given package");
-                pw.println("    k[eysets]: print known keysets");
                 return;
             } else if ("--checkin".equals(opt)) {
                 checkin = true;
@@ -11938,6 +11984,12 @@
                 dumpState.setDump(DumpState.DUMP_VERSION);
             } else if ("k".equals(cmd) || "keysets".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_KEYSETS);
+            } else if ("write".equals(cmd)) {
+                synchronized (mPackages) {
+                    mSettings.writeLPr();
+                    pw.println("Settings written.");
+                    return;
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d37b240..3ca658f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -59,6 +59,7 @@
 import android.os.FileUtils;
 import android.os.Process;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -527,8 +528,11 @@
                             // original default value is true), or we are being
                             // asked to install for all users, or this is the
                             // user we are installing for.
+                            // In this context all users (USER_ALL) implies an adb install,
+                            // so we additionally check whether that is allowed for this user.
                             final boolean installed = installUser == null
-                                    || installUser.getIdentifier() == UserHandle.USER_ALL
+                                    || (installUser.getIdentifier() == UserHandle.USER_ALL
+                                            && (!isUnknownSourcesDisallowed(user.id)))
                                     || installUser.getIdentifier() == user.id;
                             p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
                                     installed,
@@ -593,7 +597,10 @@
                 List<UserInfo> users = getAllUsers();
                 if (users != null) {
                     for (UserInfo user : users) {
-                        if (installUser.getIdentifier() == UserHandle.USER_ALL
+                        // Installing for USER_ALL implies an adb install, so we
+                        // additionally check whether that is allowed for this user.
+                        if ((installUser.getIdentifier() == UserHandle.USER_ALL
+                                        && (!isUnknownSourcesDisallowed(user.id)))
                                 || installUser.getIdentifier() == user.id) {
                             boolean installed = p.getInstalled(user.id);
                             if (!installed) {
@@ -608,6 +615,12 @@
         return p;
     }
 
+    boolean isUnknownSourcesDisallowed(int userId) {
+        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        return um.getUserRestrictions(new UserHandle(userId)).getBoolean(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
+    }
+
     void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
         p.pkg = pkg;
         // pkg.mSetEnabled = p.getEnabled(userId);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index fd180bf..102b2d4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -789,6 +789,7 @@
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
+                writeBoolean(serializer, restrictions, UserManager.DISALLOW_TELEPHONY);
                 serializer.endTag(null, TAG_RESTRICTIONS);
             }
             serializer.endTag(null, TAG_USER);
@@ -941,6 +942,7 @@
                                 UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
                         readBoolean(parser, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
                         readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
+                        readBoolean(parser, restrictions, UserManager.DISALLOW_TELEPHONY);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f0b7861..aca17bf 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -148,20 +148,9 @@
     private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
     private static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;
 
-    // Default and minimum screen off timeout in milliseconds.
+    // Default timeout in milliseconds.  This is only used until the settings
+    // provider populates the actual default value (R.integer.def_screen_off_timeout).
     private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
-    private static final int MINIMUM_SCREEN_OFF_TIMEOUT = 10 * 1000;
-
-    // The screen dim duration, in milliseconds.
-    // This is subtracted from the end of the screen off timeout so the
-    // minimum screen off timeout should be longer than this.
-    private static final int SCREEN_DIM_DURATION = 7 * 1000;
-
-    // The maximum screen dim time expressed as a ratio relative to the screen
-    // off timeout.  If the screen off timeout is very short then we want the
-    // dim timeout to also be quite short so that most of the time is spent on.
-    // Otherwise the user won't get much screen on time before dimming occurs.
-    private static final float MAXIMUM_SCREEN_DIM_RATIO = 0.2f;
 
     // The name of the boot animation service in init.rc.
     private static final String BOOT_ANIMATION_SERVICE = "bootanim";
@@ -342,6 +331,20 @@
     // True if dreams should be activated on dock.
     private boolean mDreamsActivateOnDockSetting;
 
+    // The minimum screen off timeout, in milliseconds.
+    private int mMinimumScreenOffTimeoutConfig;
+
+    // The screen dim duration, in milliseconds.
+    // This is subtracted from the end of the screen off timeout so the
+    // minimum screen off timeout should be longer than this.
+    private int mMaximumScreenDimDurationConfig;
+
+    // The maximum screen dim time expressed as a ratio relative to the screen
+    // off timeout.  If the screen off timeout is very short then we want the
+    // dim timeout to also be quite short so that most of the time is spent on.
+    // Otherwise the user won't get much screen on time before dimming occurs.
+    private float mMaximumScreenDimRatioConfig;
+
     // The screen off timeout setting value in milliseconds.
     private int mScreenOffTimeoutSetting;
 
@@ -583,6 +586,12 @@
                 com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered);
         mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
                 com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
+        mMinimumScreenOffTimeoutConfig = resources.getInteger(
+                com.android.internal.R.integer.config_minimumScreenOffTimeout);
+        mMaximumScreenDimDurationConfig = resources.getInteger(
+                com.android.internal.R.integer.config_maximumScreenDimDuration);
+        mMaximumScreenDimRatioConfig = resources.getFraction(
+                com.android.internal.R.fraction.config_maximumScreenDimRatio, 1, 1);
     }
 
     private void updateSettingsLocked() {
@@ -940,9 +949,9 @@
         return true;
     }
 
-    private void goToSleepInternal(long eventTime, int reason) {
+    private void goToSleepInternal(long eventTime, int reason, int flags) {
         synchronized (mLock) {
-            if (goToSleepNoUpdateLocked(eventTime, reason)) {
+            if (goToSleepNoUpdateLocked(eventTime, reason, flags)) {
                 updatePowerStateLocked();
             }
         }
@@ -951,9 +960,10 @@
     // This method is called goToSleep for historical reasons but we actually start
     // dozing before really going to sleep.
     @SuppressWarnings("deprecation")
-    private boolean goToSleepNoUpdateLocked(long eventTime, int reason) {
+    private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason);
+            Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
+                    + ", reason=" + reason + ", flags=" + flags);
         }
 
         if (eventTime < mLastWakeTime
@@ -996,6 +1006,11 @@
             }
         }
         EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
+
+        // Skip dozing if requested.
+        if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
+            reallyGoToSleepNoUpdateLocked(eventTime);
+        }
         return true;
     }
 
@@ -1368,12 +1383,12 @@
         if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {
             timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);
         }
-        return Math.max(timeout, MINIMUM_SCREEN_OFF_TIMEOUT);
+        return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
     }
 
     private int getScreenDimDurationLocked(int screenOffTimeout) {
-        return Math.min(SCREEN_DIM_DURATION,
-                (int)(screenOffTimeout * MAXIMUM_SCREEN_DIM_RATIO));
+        return Math.min(mMaximumScreenDimDurationConfig,
+                (int)(screenOffTimeout * mMaximumScreenDimRatioConfig));
     }
 
     /**
@@ -1399,7 +1414,7 @@
                     changed = napNoUpdateLocked(time);
                 } else {
                     changed = goToSleepNoUpdateLocked(time,
-                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0);
                 }
             }
         }
@@ -1546,7 +1561,7 @@
                 // Dream has ended or will be stopped.  Update the power state.
                 if (isItBedTimeYetLocked()) {
                     goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
-                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0);
                     updatePowerStateLocked();
                 } else {
                     wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
@@ -2158,6 +2173,9 @@
             pw.println("  mDreamsEnabledSetting=" + mDreamsEnabledSetting);
             pw.println("  mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting);
             pw.println("  mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
+            pw.println("  mMinimumScreenOffTimeoutConfig=" + mMinimumScreenOffTimeoutConfig);
+            pw.println("  mMaximumScreenDimDurationConfig=" + mMaximumScreenDimDurationConfig);
+            pw.println("  mMaximumScreenDimRatioConfig=" + mMaximumScreenDimRatioConfig);
             pw.println("  mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting);
             pw.println("  mMaximumScreenOffTimeoutFromDeviceAdmin="
                     + mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced="
@@ -2703,7 +2721,7 @@
         }
 
         @Override // Binder call
-        public void goToSleep(long eventTime, int reason) {
+        public void goToSleep(long eventTime, int reason, int flags) {
             if (eventTime > SystemClock.uptimeMillis()) {
                 throw new IllegalArgumentException("event time must not be in the future");
             }
@@ -2713,7 +2731,7 @@
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                goToSleepInternal(eventTime, reason);
+                goToSleepInternal(eventTime, reason, flags);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index c20e38c..e2d2ac6 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -26,6 +26,7 @@
 import android.os.IRemoteCallback;
 import android.os.SystemProperties;
 import android.util.Slog;
+import android.view.View;
 import android.view.WindowManager;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
@@ -34,7 +35,6 @@
 import android.view.animation.ClipRectAnimation;
 import android.view.animation.Interpolator;
 import android.view.animation.ScaleAnimation;
-
 import android.view.animation.TranslateAnimation;
 import com.android.internal.util.DumpUtils.Dump;
 import com.android.server.AttributeCache;
@@ -500,7 +500,8 @@
      */
     Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
                                                     int appHeight, int orientation, int transit,
-                                                    Rect containingFrame, Rect contentInsets) {
+                                                    Rect containingFrame, Rect contentInsets,
+                                                    boolean isFullScreen) {
         Animation a;
         final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -520,6 +521,9 @@
                     scaledTopDecor = (int) (scale * contentInsets.top);
                     int unscaledThumbHeight = (int) (thumbHeight / scale);
                     mTmpFromClipRect.set(containingFrame);
+                    if (isFullScreen) {
+                        mTmpFromClipRect.top = contentInsets.top;
+                    }
                     mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
                     mTmpToClipRect.set(containingFrame);
                 } else {
@@ -527,7 +531,12 @@
                     scale = thumbHeight / (appHeight - contentInsets.top);
                     scaledTopDecor = (int) (scale * contentInsets.top);
                     int unscaledThumbWidth = (int) (thumbWidth / scale);
+                    int unscaledThumbHeight = (int) (thumbHeight / scale);
                     mTmpFromClipRect.set(containingFrame);
+                    if (isFullScreen) {
+                        mTmpFromClipRect.top = contentInsets.top;
+                        mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
+                    }
                     mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
                     mTmpToClipRect.set(containingFrame);
                 }
@@ -575,14 +584,22 @@
                     int unscaledThumbHeight = (int) (thumbHeight / scale);
                     mTmpFromClipRect.set(containingFrame);
                     mTmpToClipRect.set(containingFrame);
+                    if (isFullScreen) {
+                        mTmpToClipRect.top = contentInsets.top;
+                    }
                     mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
                 } else {
                     // In landscape, we scale the height and clip to the top/left square
                     scale = thumbHeight / (appHeight - contentInsets.top);
                     scaledTopDecor = (int) (scale * contentInsets.top);
                     int unscaledThumbWidth = (int) (thumbWidth / scale);
+                    int unscaledThumbHeight = (int) (thumbHeight / scale);
                     mTmpFromClipRect.set(containingFrame);
                     mTmpToClipRect.set(containingFrame);
+                    if (isFullScreen) {
+                        mTmpToClipRect.top = contentInsets.top;
+                        mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+                    }
                     mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
                 }
 
@@ -679,7 +696,7 @@
 
     Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
                             int appWidth, int appHeight, int orientation,
-                            Rect containingFrame, Rect contentInsets) {
+                            Rect containingFrame, Rect contentInsets, boolean isFullScreen) {
         Animation a;
         if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
             a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -702,7 +719,7 @@
                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
             a = createAlternateThumbnailEnterExitAnimationLocked(
                     getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
-                    transit, containingFrame, contentInsets);
+                    transit, containingFrame, contentInsets, isFullScreen);
             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 c6fffbf..63a4f52 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -289,6 +289,11 @@
 
     private static final int MAX_SCREENSHOT_RETRIES = 3;
 
+    // The flag describing a full screen app window (where the app takes care of drawing under the
+    // SystemUI bars)
+    private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
+            View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+
     final private KeyguardDisableHandler mKeyguardDisableHandler;
 
     final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -3193,8 +3198,11 @@
                 }
             }
 
+            boolean isFullScreen =
+                    ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
+                            == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN);
             Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
-                    mCurConfiguration.orientation, containingFrame, contentInsets);
+                    mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen);
             if (a != null) {
                 if (DEBUG_ANIM) {
                     RuntimeException e = null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e2cd4e2..58fdcc1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2301,7 +2301,7 @@
         try {
             // Power off the display
             getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
-                    PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
+                    PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
             // Ensure the device is locked
             getWindowManager().lockNow(null);
         } catch (RemoteException e) {
@@ -2411,6 +2411,9 @@
             return;
         }
         enforceCrossUserPermission(userHandle);
+        if ((flags & DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0) {
+            enforceNotManagedProfile(userHandle, "wipe external storage");
+        }
         synchronized (this) {
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
@@ -2863,6 +2866,7 @@
             return;
         }
         enforceCrossUserPermission(userHandle);
+        enforceNotManagedProfile(userHandle, "enable/disable cameras");
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2912,6 +2916,7 @@
             return;
         }
         enforceCrossUserPermission(userHandle);
+        enforceNotManagedProfile(userHandle, "disable keyguard features");
         synchronized (this) {
             if (who == null) {
                 throw new NullPointerException("ComponentName is null");
@@ -2935,6 +2940,7 @@
             return 0;
         }
         enforceCrossUserPermission(userHandle);
+        enforceNotManagedProfile(userHandle, "list disabled keyguard features");
         synchronized (this) {
             if (who != null) {
                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
@@ -3384,6 +3390,93 @@
     }
 
     @Override
+    public boolean setApplicationBlocked(ComponentName who, String packageName,
+            boolean blocked) {
+        int callingUserId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            long id = Binder.clearCallingIdentity();
+            try {
+                IPackageManager pm = AppGlobals.getPackageManager();
+                return pm.setApplicationBlockedSettingAsUser(packageName, blocked, callingUserId);
+            } catch (RemoteException re) {
+                // shouldn't happen
+                Slog.e(LOG_TAG, "Failed to setApplicationBlockedSetting", re);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public int setApplicationsBlocked(ComponentName who, Intent intent, boolean blocked) {
+        int callingUserId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            long id = Binder.clearCallingIdentity();
+            try {
+                IPackageManager pm = AppGlobals.getPackageManager();
+                List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
+                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                        PackageManager.GET_DISABLED_COMPONENTS
+                                | PackageManager.GET_UNINSTALLED_PACKAGES,
+                        callingUserId);
+
+                if (DBG) Slog.d(LOG_TAG, "Enabling activities: " + activitiesToEnable);
+                int numberOfAppsUnblocked = 0;
+                if (activitiesToEnable != null) {
+                    for (ResolveInfo info : activitiesToEnable) {
+                        if (info.activityInfo != null) {
+                            numberOfAppsUnblocked++;
+                            pm.setApplicationBlockedSettingAsUser(info.activityInfo.packageName,
+                                    blocked, callingUserId);
+                        }
+                    }
+                }
+                return numberOfAppsUnblocked;
+            } catch (RemoteException re) {
+                // shouldn't happen
+                Slog.e(LOG_TAG, "Failed to setApplicationsBlockedSettingsWithIntent", re);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+            return 0;
+        }
+    }
+
+    @Override
+    public boolean isApplicationBlocked(ComponentName who, String packageName) {
+        int callingUserId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            long id = Binder.clearCallingIdentity();
+            try {
+                IPackageManager pm = AppGlobals.getPackageManager();
+                return pm.getApplicationBlockedSettingAsUser(packageName, callingUserId);
+            } catch (RemoteException re) {
+                // shouldn't happen
+                Slog.e(LOG_TAG, "Failed to getApplicationBlockedSettingAsUser", re);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+            return false;
+        }
+    }
+
+    @Override
     public void enableSystemApp(ComponentName who, String packageName) {
         synchronized (this) {
             if (who == null) {
@@ -3595,4 +3688,43 @@
         }
         return false;
     }
+
+    @Override
+    public void setGlobalSetting(ComponentName who, String setting, String value) {
+        final ContentResolver contentResolver = mContext.getContentResolver();
+
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+
+            long id = Binder.clearCallingIdentity();
+            try {
+                Settings.Global.putString(contentResolver, setting, value);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
+
+    @Override
+    public void setSecureSetting(ComponentName who, String setting, String value) {
+        int callingUserId = UserHandle.getCallingUserId();
+        final ContentResolver contentResolver = mContext.getContentResolver();
+
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            long id = Binder.clearCallingIdentity();
+            try {
+                Settings.Secure.putStringForUser(contentResolver, setting, value, callingUserId);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9b3f7ac..55ae9c6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -125,7 +125,7 @@
     private static final String WIFI_SERVICE_CLASS =
             "com.android.server.wifi.WifiService";
     private static final String WIFI_PASSPOINT_SERVICE_CLASS =
-            "com.android.server.wifi.passpoint.WifiPasspointService";
+            "com.android.server.wifi.passpoint.PasspointService";
     private static final String WIFI_P2P_SERVICE_CLASS =
             "com.android.server.wifi.p2p.WifiP2pService";
     private static final String HDMI_CEC_SERVICE_CLASS =
@@ -639,18 +639,18 @@
                 }
 
                 try {
-                    mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
-                } catch (Throwable e) {
-                    reportWtf("starting Wi-Fi PasspointService", e);
-                }
-
-                try {
                     mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
                 } catch (Throwable e) {
                     reportWtf("starting Wi-Fi Service", e);
                 }
 
                 try {
+                    mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
+                } catch (Throwable e) {
+                    reportWtf("starting Wi-Fi PasspointService", e);
+                }
+
+                try {
                     Slog.i(TAG, "Wi-Fi Scanning Service");
                     mSystemServiceManager.startService(
                             "com.android.server.wifi.WifiScanningService");
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 4eb70aa..00c0f93 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public void goToSleep(long arg0, int arg1) throws RemoteException {
+    public void goToSleep(long arg0, int arg1, int arg2) throws RemoteException {
         // pass for now.
     }
 
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 3e3b6e3..cfd0a51 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -16,8 +16,8 @@
 
 package android.net.wifi;
 
-import android.net.wifi.passpoint.PasspointInfo;
-import android.net.wifi.passpoint.PasspointManager;
+import android.net.wifi.passpoint.WifiPasspointInfo;
+import android.net.wifi.passpoint.WifiPasspointManager;
 import android.os.Parcelable;
 import android.os.Parcel;
 
@@ -80,10 +80,10 @@
 
     /**
      * Passpoint ANQP information. This is not fetched automatically.
-     * Use {@link PasspointManager#requestAnqpInfo} to request ANQP info.
+     * Use {@link WifiPasspointManager#requestAnqpInfo} to request ANQP info.
      * {@hide}
      */
-    public PasspointInfo passpoint;
+    public WifiPasspointInfo passpoint;
 
     /**
      * {@hide}
@@ -132,7 +132,7 @@
             distanceSdCm = source.distanceSdCm;
             seen = source.seen;
             if (source.passpoint != null)
-                passpoint = new PasspointInfo(source.passpoint);
+                passpoint = new WifiPasspointInfo(source.passpoint);
         }
     }
 
@@ -219,7 +219,7 @@
                     in.readInt()
                 );
                 if (in.readInt() == 1) {
-                    sr.passpoint = PasspointInfo.CREATOR.createFromParcel(in);
+                    sr.passpoint = WifiPasspointInfo.CREATOR.createFromParcel(in);
                 }
                 return sr;
             }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e73cce1b..292f844 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -16,9 +16,13 @@
 
 package android.net.wifi;
 
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.ProxyInfo;
 import android.net.LinkProperties;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.text.TextUtils;
 
 import java.util.HashMap;
@@ -286,20 +290,7 @@
     /**
      * @hide
      */
-    public enum IpAssignment {
-        /* Use statically configured IP settings. Configuration can be accessed
-         * with linkProperties */
-        STATIC,
-        /* Use dynamically configured IP settigns */
-        DHCP,
-        /* no IP details are assigned, this is used to indicate
-         * that any existing IP settings should be retained */
-        UNASSIGNED
-    }
-    /**
-     * @hide
-     */
-    public IpAssignment ipAssignment;
+    private IpConfiguration mIpConfiguration;
 
     /**
      * @hide
@@ -457,32 +448,6 @@
      */
     public HashMap<String, Integer>  linkedConfigurations;
 
-    /**
-     * @hide
-     */
-    public enum ProxySettings {
-        /* No proxy is to be used. Any existing proxy settings
-         * should be cleared. */
-        NONE,
-        /* Use statically configured proxy. Configuration can be accessed
-         * with linkProperties */
-        STATIC,
-        /* no proxy details are assigned, this is used to indicate
-         * that any existing proxy settings should be retained */
-        UNASSIGNED,
-        /* Use a Pac based proxy.
-         */
-        PAC
-    }
-    /**
-     * @hide
-     */
-    public ProxySettings proxySettings;
-    /**
-     * @hide
-     */
-    public LinkProperties linkProperties;
-
     public WifiConfiguration() {
         networkId = INVALID_NETWORK_ID;
         SSID = null;
@@ -500,12 +465,10 @@
             wepKeys[i] = null;
         }
         enterpriseConfig = new WifiEnterpriseConfig();
-        ipAssignment = IpAssignment.UNASSIGNED;
-        proxySettings = ProxySettings.UNASSIGNED;
-        linkProperties = new LinkProperties();
         autoJoinStatus = AUTO_JOIN_ENABLED;
         selfAdded = false;
         ephemeral = false;
+        mIpConfiguration = new IpConfiguration();
     }
 
     /**
@@ -640,12 +603,7 @@
         sbuf.append(enterpriseConfig);
         sbuf.append('\n');
 
-        sbuf.append("IP assignment: " + ipAssignment.toString());
-        sbuf.append("\n");
-        sbuf.append("Proxy settings: " + proxySettings.toString());
-        sbuf.append("\n");
-        sbuf.append(linkProperties.toString());
-        sbuf.append("\n");
+        sbuf.append(mIpConfiguration.toString());
 
         return sbuf.toString();
     }
@@ -823,6 +781,52 @@
         return key;
     }
 
+    /** @hide */
+    public IpConfiguration getIpConfiguration() {
+        return mIpConfiguration;
+    }
+
+    /** @hide */
+    public void setIpConfiguration(IpConfiguration ipConfiguration) {
+        mIpConfiguration = ipConfiguration;
+    }
+
+    /** @hide */
+    public LinkProperties getLinkProperties() {
+        return mIpConfiguration.linkProperties;
+    }
+
+    /** @hide */
+    public void setLinkProperties(LinkProperties linkProperties) {
+        mIpConfiguration.linkProperties = linkProperties;
+    }
+
+    /** @hide */
+    public IpConfiguration.IpAssignment getIpAssignment() {
+        return mIpConfiguration.ipAssignment;
+    }
+
+    /** @hide */
+    public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) {
+        mIpConfiguration.ipAssignment = ipAssignment;
+    }
+
+    /** @hide */
+    public IpConfiguration.ProxySettings getProxySettings() {
+        return mIpConfiguration.proxySettings;
+    }
+
+    /** @hide */
+    public void setProxySettings(IpConfiguration.ProxySettings proxySettings) {
+        mIpConfiguration.proxySettings = proxySettings;
+    }
+
+    /** @hide */
+    public void setProxy(ProxySettings settings, ProxyInfo proxy) {
+        mIpConfiguration.proxySettings = settings;
+        mIpConfiguration.linkProperties.setHttpProxy(proxy);
+    }
+
     /** Implement the Parcelable interface {@hide} */
     public int describeContents() {
         return 0;
@@ -854,12 +858,10 @@
 
             enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
 
-            ipAssignment = source.ipAssignment;
-            proxySettings = source.proxySettings;
-
             defaultGwMacAddress = source.defaultGwMacAddress;
 
-            linkProperties = new LinkProperties(source.linkProperties);
+            mIpConfiguration = new IpConfiguration(source.mIpConfiguration);
+
             if ((source.scanResultCache != null) && (source.scanResultCache.size() > 0)) {
                 scanResultCache = new HashMap<String, ScanResult>();
                 scanResultCache.putAll(source.scanResultCache);
@@ -882,10 +884,11 @@
             if (source.visibility != null) {
                 visibility = new Visibility(source.visibility);
             }
-       }
+        }
     }
 
     /** Implement the Parcelable interface {@hide} */
+    @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(networkId);
         dest.writeInt(status);
@@ -908,10 +911,7 @@
 
         dest.writeParcelable(enterpriseConfig, flags);
 
-        dest.writeString(ipAssignment.name());
-        dest.writeString(proxySettings.name());
-        dest.writeParcelable(linkProperties, flags);
-
+        dest.writeParcelable(mIpConfiguration, flags);
         dest.writeString(dhcpServer);
         dest.writeString(defaultGwMacAddress);
         dest.writeInt(autoJoinStatus);
@@ -943,10 +943,7 @@
 
                 config.enterpriseConfig = in.readParcelable(null);
 
-                config.ipAssignment = IpAssignment.valueOf(in.readString());
-                config.proxySettings = ProxySettings.valueOf(in.readString());
-                config.linkProperties = in.readParcelable(null);
-
+                config.mIpConfiguration = in.readParcelable(null);
                 config.dhcpServer = in.readString();
                 config.defaultGwMacAddress = in.readString();
                 config.autoJoinStatus = in.readInt();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 69be2cf..1484d49 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -224,8 +224,12 @@
         public static final int TTLS    = 2;
         /** EAP-Password */
         public static final int PWD     = 3;
+        /** EAP-Subscriber Identity Module */
+        public static final int SIM     = 4;
+        /** EAP-Authentication and Key Agreement */
+        public static final int AKA     = 5;
         /** @hide */
-        public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD" };
+        public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA" };
 
         /** Prevent initialization */
         private Eap() {}
@@ -271,6 +275,8 @@
             case Eap.PWD:
             case Eap.TLS:
             case Eap.TTLS:
+            case Eap.SIM:
+            case Eap.AKA:
                 mFields.put(EAP_KEY, Eap.strings[eapMethod]);
                 mFields.put(OPP_KEY_CACHING, "1");
                 break;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9558d50..c6ce768 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1413,14 +1413,12 @@
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation failed due to an internal error.
-     * @hide
      */
     public static final int ERROR                       = 0;
 
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation is already in progress
-     * @hide
      */
     public static final int IN_PROGRESS                 = 1;
 
@@ -1428,30 +1426,28 @@
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation failed because the framework is busy and
      * unable to service the request
-     * @hide
      */
     public static final int BUSY                        = 2;
 
     /* WPS specific errors */
-    /** WPS overlap detected {@hide} */
+    /** WPS overlap detected */
     public static final int WPS_OVERLAP_ERROR           = 3;
-    /** WEP on WPS is prohibited {@hide} */
+    /** WEP on WPS is prohibited */
     public static final int WPS_WEP_PROHIBITED          = 4;
-    /** TKIP only prohibited {@hide} */
+    /** TKIP only prohibited */
     public static final int WPS_TKIP_ONLY_PROHIBITED    = 5;
-    /** Authentication failure on WPS {@hide} */
+    /** Authentication failure on WPS */
     public static final int WPS_AUTH_FAILURE            = 6;
-    /** WPS timed out {@hide} */
+    /** WPS timed out */
     public static final int WPS_TIMED_OUT               = 7;
 
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation failed due to invalid inputs
-     * @hide
      */
     public static final int INVALID_ARGS                = 8;
 
-    /** Interface for callback invocation on an application action {@hide} */
+    /** Interface for callback invocation on an application action */
     public interface ActionListener {
         /** The operation succeeded */
         public void onSuccess();
@@ -1463,7 +1459,7 @@
         public void onFailure(int reason);
     }
 
-    /** Interface for callback invocation on a start WPS action {@hide} */
+    /** Interface for callback invocation on a start WPS action */
     public interface WpsListener {
         /** WPS start succeeded */
         public void onStartSuccess(String pin);
@@ -1745,7 +1741,6 @@
      * @param listener for callbacks on success or failure. Can be null.
      * @throws IllegalStateException if the WifiManager instance needs to be
      * initialized again
-     * @hide
      */
     public void startWps(WpsInfo config, WpsListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
@@ -1759,7 +1754,6 @@
      * @param listener for callbacks on success or failure. Can be null.
      * @throws IllegalStateException if the WifiManager instance needs to be
      * initialized again
-     * @hide
      */
     public void cancelWps(ActionListener listener) {
         validateChannel();
diff --git a/wifi/java/android/net/wifi/WpsInfo.java b/wifi/java/android/net/wifi/WpsInfo.java
index 2ad4ad0..ae2e771 100644
--- a/wifi/java/android/net/wifi/WpsInfo.java
+++ b/wifi/java/android/net/wifi/WpsInfo.java
@@ -40,7 +40,7 @@
     /** Wi-Fi Protected Setup. www.wi-fi.org/wifi-protected-setup has details */
     public int setup;
 
-    /** @hide */
+    /** Passed with pin method KEYPAD */
     public String BSSID;
 
     /** Passed with pin method configuration */
diff --git a/wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
similarity index 87%
rename from wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl
rename to wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
index e57db64..8375d09 100644
--- a/wifi/java/android/net/wifi/passpoint/IPasspointManager.aidl
+++ b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
@@ -19,11 +19,11 @@
 import android.os.Messenger;
 
 /**
- * Interface that allows controlling and querying Passpoint connectivity.
+ * Interface that allows controlling and querying Wifi Passpoint connectivity.
  *
  * {@hide}
  */
-interface IPasspointManager
+interface IWifiPasspointManager
 {
     Messenger getMessenger();
     int getPasspointState();
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl b/wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl
deleted file mode 100644
index 6f75cbe..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointCredential.aidl
+++ /dev/null
@@ -1,19 +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.passpoint;
-
-parcelable PasspointCredential;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointCredential.java b/wifi/java/android/net/wifi/passpoint/PasspointCredential.java
deleted file mode 100644
index 4218f23..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointCredential.java
+++ /dev/null
@@ -1,56 +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.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/passpoint/PasspointInfo.java b/wifi/java/android/net/wifi/passpoint/PasspointInfo.java
deleted file mode 100644
index d57b0aa..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointInfo.java
+++ /dev/null
@@ -1,274 +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.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/PasspointPolicy.aidl b/wifi/java/android/net/wifi/passpoint/PasspointPolicy.aidl
deleted file mode 100644
index c2cc731..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointPolicy.aidl
+++ /dev/null
@@ -1,19 +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.passpoint;
-
-parcelable PasspointPolicy;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java b/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java
deleted file mode 100644
index 3a8806b..0000000
--- a/wifi/java/android/net/wifi/passpoint/PasspointPolicy.java
+++ /dev/null
@@ -1,55 +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.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/passpoint/PasspointOsuProvider.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
similarity index 94%
rename from wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
rename to wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
index f5ecb7c..cfd3605 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.passpoint;
 
-parcelable PasspointOsuProvider;
+parcelable WifiPasspointCredential;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java
new file mode 100644
index 0000000..08b430f
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java
@@ -0,0 +1,711 @@
+/*
+ * 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.net.wifi.WifiEnterpriseConfig;
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.Map;
+
+public class WifiPasspointCredential implements Parcelable {
+
+    private final static String TAG = "PasspointCredential";
+    private String mWifiSPFQDN;
+    private String mCredentialName;
+    private String mUpdateIdentifier;
+    private String mSubscriptionUpdateMethod;
+    private String mType;
+    private String mInnerMethod;
+    private String mCertType;
+    private String mCertSha256Fingerprint;
+    private String mUsername;
+    private String mPasswd;
+    private String mImsi;
+    private String mMcc;
+    private String mMnc;
+    private String mCaRootCert;
+    private String mRealm;
+    private int mPriority; //User preferred priority; The smaller, the higher
+    private boolean mUserPreferred = false;
+    private String mHomeSpFqdn;
+    private String mFriendlyName;
+    private String mOtherhomepartnerFqdn;
+    private String mClientCert;
+    private String mCreationDate;
+    private String mExpirationDate;
+
+    private String mSubscriptionDMAccUsername;
+    private String mSubscriptionDMAccPassword;
+    private String mSubscriptionUpdateInterval;
+
+    private String mPolicyUpdateURI;
+    private String mPolicyUpdateInterval;
+    private String mPolicyDMAccUsername;
+    private String mPolicyDMAccPassword;
+    private String mPolicyUpdateRestriction;
+    private String mPolicyUpdateMethod;
+
+    private Collection<WifiPasspointDmTree.PreferredRoamingPartnerList> mPreferredRoamingPartnerList;
+    private Collection<WifiPasspointDmTree.HomeOIList> mHomeOIList;
+    private Collection<WifiPasspointDmTree.MinBackhaulThresholdNetwork> mMinBackhaulThresholdNetwork;
+    private Collection<WifiPasspointDmTree.RequiredProtoPortTuple> mRequiredProtoPortTuple;
+    private Collection<WifiPasspointDmTree.SPExclusionList> mSpExclusionList;
+    private String mMaxBssLoad;
+
+    private boolean mIsMachineRemediation;
+
+    private String mAAACertURL;
+    private String mAAASha256Fingerprint;
+
+    private String mSubscriptionUpdateRestriction;
+    private String mSubscriptionUpdateURI;
+
+    private boolean mCheckAaaServerCertStatus;
+
+    /** @hide */
+    public WifiPasspointCredential() {
+
+    }
+
+    /**
+     * Constructor
+     * @param realm Realm of the passpoint credential
+     * @param config Credential information, must be either EAP-TLS or EAP-TTLS.
+     * @see WifiEnterpriseConfig
+     */
+    public WifiPasspointCredential(String realm, WifiEnterpriseConfig config) {
+        mRealm = realm;
+        switch (config.getEapMethod()) {
+            case WifiEnterpriseConfig.Eap.TLS:
+                // TODO;
+                break;
+            case WifiEnterpriseConfig.Eap.TTLS:
+                // TODO;
+                break;
+            default:
+                // ignore
+        }
+    }
+
+    /** @hide */
+    public WifiPasspointCredential(String type,
+            String caroot,
+            String clientcert,
+            WifiPasspointDmTree.SpFqdn sp,
+            WifiPasspointDmTree.CredentialInfo credinfo) {
+
+        if (credinfo == null) {
+            return;
+        }
+
+        mType = type;
+        mCaRootCert = caroot;
+        mClientCert = clientcert;
+
+        mWifiSPFQDN = sp.nodeName;
+        mUpdateIdentifier = sp.perProviderSubscription.UpdateIdentifier;
+
+        mCredentialName = credinfo.nodeName;
+        Set set = credinfo.homeSP.otherHomePartners.entrySet();
+        Iterator i = set.iterator();
+        if (i.hasNext()) {
+            Map.Entry entry3 = (Map.Entry) i.next();
+            WifiPasspointDmTree.OtherHomePartners ohp = (WifiPasspointDmTree.OtherHomePartners) entry3.getValue();
+            mOtherhomepartnerFqdn = ohp.FQDN;
+        }
+
+        set = credinfo.aAAServerTrustRoot.entrySet();
+        i = set.iterator();
+        if (i.hasNext()) {
+            Map.Entry entry3 = (Map.Entry) i.next();
+            WifiPasspointDmTree.AAAServerTrustRoot aaa = (WifiPasspointDmTree.AAAServerTrustRoot) entry3.getValue();
+            mAAACertURL = aaa.CertURL;
+            mAAASha256Fingerprint = aaa.CertSHA256Fingerprint;
+        }
+
+        mCertType = credinfo.credential.digitalCertificate.CertificateType;
+        mCertSha256Fingerprint = credinfo.credential.digitalCertificate.CertSHA256Fingerprint;
+        mUsername = credinfo.credential.usernamePassword.Username;
+        mPasswd = credinfo.credential.usernamePassword.Password;
+        mIsMachineRemediation = credinfo.credential.usernamePassword.MachineManaged;
+        mInnerMethod = credinfo.credential.usernamePassword.eAPMethod.InnerMethod;
+        mImsi = credinfo.credential.sim.IMSI;
+        mCreationDate = credinfo.credential.CreationDate;
+        mExpirationDate = credinfo.credential.ExpirationDate;
+        mRealm = credinfo.credential.Realm;
+
+        if (credinfo.credentialPriority == null) {
+            credinfo.credentialPriority = "128";
+        }
+        mPriority = Integer.parseInt(credinfo.credentialPriority);
+
+        mHomeSpFqdn = credinfo.homeSP.FQDN;
+
+        mSubscriptionUpdateInterval = credinfo.subscriptionUpdate.UpdateInterval;
+        mSubscriptionUpdateMethod = credinfo.subscriptionUpdate.UpdateMethod;
+        mSubscriptionUpdateRestriction = credinfo.subscriptionUpdate.Restriction;
+        mSubscriptionUpdateURI = credinfo.subscriptionUpdate.URI;
+        mSubscriptionDMAccUsername = credinfo.subscriptionUpdate.usernamePassword.Username;
+        mSubscriptionDMAccPassword = credinfo.subscriptionUpdate.usernamePassword.Password;
+
+        mPolicyUpdateURI = credinfo.policy.policyUpdate.URI;
+        mPolicyUpdateInterval = credinfo.policy.policyUpdate.UpdateInterval;
+        mPolicyDMAccUsername = credinfo.policy.policyUpdate.usernamePassword.Username;
+        mPolicyDMAccPassword = credinfo.policy.policyUpdate.usernamePassword.Password;
+        mPolicyUpdateRestriction = credinfo.policy.policyUpdate.Restriction;
+        mPolicyUpdateMethod = credinfo.policy.policyUpdate.UpdateMethod;
+        mPreferredRoamingPartnerList = credinfo.policy.preferredRoamingPartnerList.values();
+        mMinBackhaulThresholdNetwork = credinfo.policy.minBackhaulThreshold.values();
+        mRequiredProtoPortTuple = credinfo.policy.requiredProtoPortTuple.values();
+        mMaxBssLoad = credinfo.policy.maximumBSSLoadValue;
+        mSpExclusionList = credinfo.policy.sPExclusionList.values();
+
+        mHomeOIList = credinfo.homeSP.homeOIList.values();
+        mFriendlyName = credinfo.homeSP.FriendlyName;
+        mCheckAaaServerCertStatus = credinfo.credential.CheckAAAServerCertStatus;
+    }
+
+    /** @hide */
+    public WifiPasspointCredential(String type,
+            String caroot,
+            String clientcert,
+            String mcc,
+            String mnc,
+            WifiPasspointDmTree.SpFqdn sp,
+            WifiPasspointDmTree.CredentialInfo credinfo) {
+
+        if (credinfo == null) {
+            return;
+        }
+
+        mType = type;
+        mCaRootCert = caroot;
+        mClientCert = clientcert;
+
+        mWifiSPFQDN = sp.nodeName;
+        mUpdateIdentifier = sp.perProviderSubscription.UpdateIdentifier;
+
+        mCredentialName = credinfo.nodeName;
+        Set set = credinfo.homeSP.otherHomePartners.entrySet();
+        Iterator i = set.iterator();
+        if (i.hasNext()) {
+            Map.Entry entry3 = (Map.Entry) i.next();
+            WifiPasspointDmTree.OtherHomePartners ohp = (WifiPasspointDmTree.OtherHomePartners) entry3.getValue();
+            mOtherhomepartnerFqdn = ohp.FQDN;
+        }
+
+        set = credinfo.aAAServerTrustRoot.entrySet();
+        i = set.iterator();
+        if (i.hasNext()) {
+            Map.Entry entry3 = (Map.Entry) i.next();
+            WifiPasspointDmTree.AAAServerTrustRoot aaa = (WifiPasspointDmTree.AAAServerTrustRoot) entry3.getValue();
+            mAAACertURL = aaa.CertURL;
+            mAAASha256Fingerprint = aaa.CertSHA256Fingerprint;
+        }
+
+        mCertType = credinfo.credential.digitalCertificate.CertificateType;
+        mCertSha256Fingerprint = credinfo.credential.digitalCertificate.CertSHA256Fingerprint;
+        mUsername = credinfo.credential.usernamePassword.Username;
+        mPasswd = credinfo.credential.usernamePassword.Password;
+        mIsMachineRemediation = credinfo.credential.usernamePassword.MachineManaged;
+        mInnerMethod = credinfo.credential.usernamePassword.eAPMethod.InnerMethod;
+        mImsi = credinfo.credential.sim.IMSI;
+        mMcc = mcc;
+        mMnc = mnc;
+        mCreationDate = credinfo.credential.CreationDate;
+        mExpirationDate = credinfo.credential.ExpirationDate;
+        mRealm = credinfo.credential.Realm;
+
+        if (credinfo.credentialPriority == null) {
+            credinfo.credentialPriority = "128";
+        }
+        mPriority = Integer.parseInt(credinfo.credentialPriority);
+
+        mHomeSpFqdn = credinfo.homeSP.FQDN;
+
+        mSubscriptionUpdateMethod = credinfo.subscriptionUpdate.UpdateMethod;
+        mSubscriptionUpdateRestriction = credinfo.subscriptionUpdate.Restriction;
+        mSubscriptionUpdateURI = credinfo.subscriptionUpdate.URI;
+        mSubscriptionDMAccUsername = credinfo.subscriptionUpdate.usernamePassword.Username;
+        mSubscriptionDMAccPassword = credinfo.subscriptionUpdate.usernamePassword.Password;
+
+        mPolicyUpdateURI = credinfo.policy.policyUpdate.URI;
+        mPolicyUpdateInterval = credinfo.policy.policyUpdate.UpdateInterval;
+        mPolicyDMAccUsername = credinfo.policy.policyUpdate.usernamePassword.Username;
+        mPolicyDMAccPassword = credinfo.policy.policyUpdate.usernamePassword.Password;
+        mPolicyUpdateRestriction = credinfo.policy.policyUpdate.Restriction;
+        mPolicyUpdateMethod = credinfo.policy.policyUpdate.UpdateMethod;
+        mPreferredRoamingPartnerList = credinfo.policy.preferredRoamingPartnerList.values();
+        mMinBackhaulThresholdNetwork = credinfo.policy.minBackhaulThreshold.values();
+        mRequiredProtoPortTuple = credinfo.policy.requiredProtoPortTuple.values();
+        mMaxBssLoad = credinfo.policy.maximumBSSLoadValue;
+        mSpExclusionList = credinfo.policy.sPExclusionList.values();
+
+        mHomeOIList = credinfo.homeSP.homeOIList.values();
+        mFriendlyName = credinfo.homeSP.FriendlyName;
+    }
+
+    /** @hide */
+    public String getUpdateIdentifier() {
+        return mUpdateIdentifier;
+    }
+
+    /** @hide */
+    public String getUpdateMethod() {
+        return mSubscriptionUpdateMethod;
+    }
+
+    /** @hide */
+    public void setUpdateMethod(String method) {
+        mSubscriptionUpdateMethod = method;
+    }
+
+    /** @hide */
+    public String getWifiSPFQDN() {
+        return mWifiSPFQDN;
+    }
+
+    /** @hide */
+    public String getCredName() {
+        return mCredentialName;
+    }
+
+    /** @hide */
+    public String getEapMethodStr() {
+        return mType;
+    }
+
+    /**
+     * Get EAP method of this Passpoint credential.
+     * @return EAP method, refer to {@link WifiEnterpriseConfig.Eap} for possible return values
+     */
+    public int getEapMethod() {
+        return 0;
+    }
+
+    /** @hide */
+    public String getCertType() {
+        return mCertType;
+    }
+
+    /** @hide */
+    public String getCertSha256Fingerprint() {
+        return mCertSha256Fingerprint;
+    }
+
+    /**
+     * Get the user name of this Passpoint credential, for EAP-TTLS only.
+     * @return user name
+     */
+    public String getUserName() {
+        return mUsername;
+    }
+
+    /** @hide */
+    public String getPassword() {
+        // TODO: guarded by connectivity internal
+        return mPasswd;
+    }
+
+    /**
+     * Get the IMSI of this Passpoint credential, for EAP-SIM / EAP-AKA only.
+     * @return IMSI
+     */
+    public String getImsi() {
+        return mImsi;
+    }
+
+    /** @hide */
+    public String getMcc() {
+        return mMcc;
+    }
+
+    /** @hide */
+    public String getMnc() {
+        return mMnc;
+    }
+
+    /** @hide */
+    public String getCaRootCert() {
+        return mCaRootCert;
+    }
+
+    /**
+     * Get the client certificate path of this Passpoint credential, for EAP-TLS only.
+     * @return client certificate path
+     */
+    public String getClientCertPath() {
+        return mClientCert;
+    }
+
+    /**
+     * Get the realm of this Passpoint credential, for all EAP methods.
+     * @return Realm
+     */
+    public String getRealm() {
+        return mRealm;
+    }
+
+    /** @hide */
+    public int getPriority() {
+        if (mUserPreferred) {
+            return 0;
+        }
+
+        return mPriority;
+    }
+
+    /**
+     * Get the fully qualified domain name (FQDN) of this Passpoint credential,
+     * for all EAP methods.
+     * @return FQDN
+     */
+    public String getFqdn() {
+        return mHomeSpFqdn;
+    }
+
+    /** @hide */
+    public String getOtherhomepartners() {
+        return mOtherhomepartnerFqdn;
+    }
+
+    /** @hide */
+    public String getSubscriptionDMAccUsername() {
+        return mSubscriptionDMAccUsername;
+    }
+
+    /** @hide */
+    public String getSubscriptionDMAccPassword() {
+        return mSubscriptionDMAccPassword;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateURI() {
+        return mPolicyUpdateURI;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateInterval() {
+        return mPolicyUpdateInterval;
+    }
+
+    /** @hide */
+    public String getPolicyDMAccUsername() {
+        return mPolicyDMAccUsername;
+    }
+
+    /** @hide */
+    public String getPolicyDMAccPassword() {
+        return mPolicyDMAccPassword;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateRestriction() {
+        return mPolicyUpdateRestriction;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateMethod() {
+        return mPolicyUpdateMethod;
+    }
+
+    /** @hide */
+    public String getCreationDate() {
+        return mCreationDate;
+    }
+
+    /** @hide */
+    public String getExpirationDate() {
+        return mExpirationDate;
+    }
+
+    /** @hide */
+    public void setExpirationDate(String expirationdate) {
+        mExpirationDate = expirationdate;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.PreferredRoamingPartnerList> getPrpList() {
+        return mPreferredRoamingPartnerList;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.HomeOIList> getHomeOIList() {
+        return mHomeOIList;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.MinBackhaulThresholdNetwork> getBackhaulThresholdList() {
+        return mMinBackhaulThresholdNetwork;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.RequiredProtoPortTuple> getRequiredProtoPortList() {
+        return mRequiredProtoPortTuple;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.SPExclusionList> getSPExclusionList() {
+        return mSpExclusionList;
+    }
+
+    /** @hide */
+    public boolean getIsMachineRemediation() {
+        return mIsMachineRemediation;
+    }
+
+    /** @hide */
+    public String getAAACertURL() {
+        return mAAACertURL;
+    }
+
+    /** @hide */
+    public String getAAASha256Fingerprint() {
+        return mAAASha256Fingerprint;
+    }
+
+    /** @hide */
+    public String getSubscriptionUpdateRestriction() {
+        return mSubscriptionUpdateRestriction;
+    }
+
+    /** @hide */
+    public String getSubscriptionUpdateURI() {
+        return mSubscriptionUpdateURI;
+    }
+
+    /** @hide */
+    public String getSubscriptionUpdateInterval() {
+        return mSubscriptionUpdateInterval;
+    }
+
+    /** @hide */
+    public String getFriendlyName() {
+        return mFriendlyName;
+    }
+
+    /** @hide */
+    public String getMaxBssLoad() {
+        return mMaxBssLoad;
+    }
+
+    /** @hide */
+    public boolean getUserPreference() {
+        return mUserPreferred;
+    }
+
+    /** @hide */
+    public boolean getCheckAaaServerCertStatus() {
+        return mCheckAaaServerCertStatus;
+    }
+
+    /** @hide */
+    public void setUserPreference(boolean value) {
+        mUserPreferred = value;
+    }
+
+    @Override
+    /** @hide */
+    public boolean equals(Object obj) {
+        boolean result = false;
+        if (obj instanceof WifiPasspointCredential) {
+            final WifiPasspointCredential other = (WifiPasspointCredential) obj;
+            if (this.mType.equals(other.mType)) {
+                if (this.mType.equals("TTLS")) {
+                    result = this.mUsername.equals(other.mUsername) &&
+                            this.mPasswd.equals(other.mPasswd) &&
+                            this.mRealm.equals(other.mRealm) &&
+                            this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+                }
+                if (this.mType.equals("TLS")) {
+                    result = this.mRealm.equals(other.mRealm) &&
+                            this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+                }
+                if (this.mType.equals("SIM")) {
+                    result = this.mMcc.equals(other.mMcc) &&
+                            this.mMnc.equals(other.mMnc) &&
+                            this.mImsi.equals(other.mImsi) &&
+                            this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    /** @hide */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        String none = "<none>";
+
+        sb.append(", UpdateIdentifier: ")
+                .append(mUpdateIdentifier == null ? none : mUpdateIdentifier).
+                append(", SubscriptionUpdateMethod: ")
+                .append(mSubscriptionUpdateMethod == null ? none : mSubscriptionUpdateMethod).
+                append(", Type: ").append(mType == null ? none : mType).
+                append(", Username: ").append(mUsername == null ? none : mUsername).
+                append(", Passwd: ").append(mPasswd == null ? none : mPasswd).
+                append(", SubDMAccUsername: ")
+                .append(mSubscriptionDMAccUsername == null ? none : mSubscriptionDMAccUsername).
+                append(", SubDMAccPassword: ")
+                .append(mSubscriptionDMAccPassword == null ? none : mSubscriptionDMAccPassword).
+                append(", PolDMAccUsername: ")
+                .append(mPolicyDMAccUsername == null ? none : mPolicyDMAccUsername).
+                append(", PolDMAccPassword: ")
+                .append(mPolicyDMAccPassword == null ? none : mPolicyDMAccPassword).
+                append(", Imsi: ").append(mImsi == null ? none : mImsi).
+                append(", Mcc: ").append(mMcc == null ? none : mMcc).
+                append(", Mnc: ").append(mMnc == null ? none : mMnc).
+                append(", CaRootCert: ").append(mCaRootCert == null ? none : mCaRootCert).
+                append(", Realm: ").append(mRealm == null ? none : mRealm).
+                append(", Priority: ").append(mPriority).
+                append(", Fqdn: ").append(mHomeSpFqdn == null ? none : mHomeSpFqdn).
+                append(", Otherhomepartners: ")
+                .append(mOtherhomepartnerFqdn == null ? none : mOtherhomepartnerFqdn).
+                append(", ExpirationDate: ")
+                .append(mExpirationDate == null ? none : mExpirationDate).
+                append(", MaxBssLoad: ").append(mMaxBssLoad == null ? none : mMaxBssLoad).
+                append(", SPExclusionList: ").append(mSpExclusionList);
+
+        if (mPreferredRoamingPartnerList != null) {
+            sb.append("PreferredRoamingPartnerList:");
+            for (WifiPasspointDmTree.PreferredRoamingPartnerList prpListItem : mPreferredRoamingPartnerList) {
+                sb.append("[fqdnmatch:").append(prpListItem.FQDN_Match).
+                        append(", priority:").append(prpListItem.Priority).
+                        append(", country:").append(prpListItem.Country).append("]");
+            }
+        }
+
+        if (mHomeOIList != null) {
+            sb.append("HomeOIList:");
+            for (WifiPasspointDmTree.HomeOIList HomeOIListItem : mHomeOIList) {
+                sb.append("[HomeOI:").append(HomeOIListItem.HomeOI).
+                        append(", HomeOIRequired:").append(HomeOIListItem.HomeOIRequired).
+                        append("]");
+            }
+        }
+
+        if (mMinBackhaulThresholdNetwork != null) {
+            sb.append("BackHaulThreshold:");
+            for (WifiPasspointDmTree.MinBackhaulThresholdNetwork BhtListItem : mMinBackhaulThresholdNetwork) {
+                sb.append("[networkType:").append(BhtListItem.NetworkType).
+                        append(", dlBandwidth:").append(BhtListItem.DLBandwidth).
+                        append(", ulBandwidth:").append(BhtListItem.ULBandwidth).
+                        append("]");
+            }
+        }
+
+        if (mRequiredProtoPortTuple != null) {
+            sb.append("WifiMORequiredProtoPortTupleList:");
+            for (WifiPasspointDmTree.RequiredProtoPortTuple RpptListItem : mRequiredProtoPortTuple) {
+                sb.append("[IPProtocol:").append(RpptListItem.IPProtocol).
+                        append(", PortNumber:").append(RpptListItem.PortNumber).
+                        append("]");
+            }
+        }
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mType);
+        dest.writeString(mUsername);
+        dest.writeString(mPasswd);
+        dest.writeString(mImsi);
+        dest.writeString(mMcc);
+        dest.writeString(mMnc);
+        dest.writeString(mCaRootCert);
+        dest.writeString(mRealm);
+        dest.writeInt(mPriority);
+        dest.writeString(mHomeSpFqdn);
+        dest.writeString(mOtherhomepartnerFqdn);
+        dest.writeString(mClientCert);
+        dest.writeString(mExpirationDate);
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiPasspointCredential> CREATOR =
+            new Creator<WifiPasspointCredential>() {
+                public WifiPasspointCredential createFromParcel(Parcel in) {
+                    WifiPasspointCredential pc = new WifiPasspointCredential();
+                    pc.mType = in.readString();
+                    pc.mUsername = in.readString();
+                    pc.mPasswd = in.readString();
+                    pc.mImsi = in.readString();
+                    pc.mMcc = in.readString();
+                    pc.mMnc = in.readString();
+                    pc.mCaRootCert = in.readString();
+                    pc.mRealm = in.readString();
+                    pc.mPriority = in.readInt();
+                    pc.mHomeSpFqdn = in.readString();
+                    pc.mOtherhomepartnerFqdn = in.readString();
+                    pc.mClientCert = in.readString();
+                    pc.mExpirationDate = in.readString();
+                    return pc;
+                }
+
+                public WifiPasspointCredential[] newArray(int size) {
+                    return new WifiPasspointCredential[size];
+                }
+            };
+
+    /** @hide */
+    public int compareTo(WifiPasspointCredential another) {
+
+        //The smaller the higher
+        if (mPriority < another.mPriority) {
+            return -1;
+        } else if (mPriority == another.mPriority) {
+            return this.mType.compareTo(another.mType);
+        } else {
+            return 1;
+        }
+    }
+
+    @Override
+    /** @hide */
+    public int hashCode() {
+        int hash = 208;
+        if (mType != null) {
+            hash += mType.hashCode();
+        }
+        if (mRealm != null) {
+            hash += mRealm.hashCode();
+        }
+        if (mHomeSpFqdn != null) {
+            hash += mHomeSpFqdn.hashCode();
+        }
+        if (mUsername != null) {
+            hash += mUsername.hashCode();
+        }
+        if (mPasswd != null) {
+            hash += mPasswd.hashCode();
+        }
+
+        return hash;
+    }
+}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
similarity index 95%
copy from wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
copy to wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
index cc11045..6a88b2e 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.passpoint;
 
-parcelable PasspointInfo;
+parcelable WifiPasspointDmTree;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java
new file mode 100644
index 0000000..9ff1973
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java
@@ -0,0 +1,1379 @@
+/*
+ * 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;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * Required Mobile Device Management Tree Structure
+ *
+ *                           +----------+
+ *                           | ./(Root) |
+ *                           +----+-----+
+ *                                |
+ *          +---------+           |         +---------+   +---------+
+ *          | DevInfo |-----------+---------| Wi-Fi   |---|SP FQDN* |
+ *          +---------+           |         +---------+   +---------+
+ *          +---------+           |
+ *          |DevDetail|-----------+
+ *          +---------+
+ *
+ * For example,
+ * ./Wi-Fi/wi-fi.org/PerproviderSubscription/Cred01/Policy/PreferredRoamingPartnerList/Roa01/FQDN_Math
+ *
+ * This class contains all nodes start from Wi-Fi
+ * @hide
+ **/
+public class WifiPasspointDmTree implements Parcelable {
+    private final static String TAG = "WifiTree";
+    public int PpsMoId;//plugfest used only
+    public HashMap<String, SpFqdn> spFqdn = new HashMap<String, SpFqdn>();//Maps.newHashMap();
+
+    public SpFqdn createSpFqdn(String name) {
+        SpFqdn obj = new SpFqdn(name);
+        spFqdn.put(name, obj);
+        return obj;
+    }
+
+    public static class SpFqdn implements Parcelable {
+        public String nodeName;
+        public PerProviderSubscription perProviderSubscription = new PerProviderSubscription();
+
+        public SpFqdn(String name) {
+            nodeName = name;
+        }
+
+        public SpFqdn() {
+        }
+
+        public SpFqdn(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeParcelable(perProviderSubscription, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                perProviderSubscription = in.readParcelable(PerProviderSubscription.class
+                        .getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<SpFqdn> CREATOR = new Parcelable.Creator<SpFqdn>() {
+            public SpFqdn createFromParcel(Parcel in) {
+                return new SpFqdn(in);
+            }
+
+            public SpFqdn[] newArray(int size) {
+                return new SpFqdn[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription
+     **/
+    public static class PerProviderSubscription implements Parcelable {
+        /**
+         * PerProviderSubscription/UpdateIdentifier
+         **/
+        public String UpdateIdentifier;
+        public HashMap<String, CredentialInfo> credentialInfo = new HashMap<String, CredentialInfo>();
+
+        public CredentialInfo createCredentialInfo(String name) {
+            CredentialInfo obj = new CredentialInfo(name);
+            credentialInfo.put(name, obj);
+            return obj;
+        }
+
+        public PerProviderSubscription() {
+        }
+
+        public PerProviderSubscription(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(UpdateIdentifier);
+            out.writeMap(credentialInfo);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                UpdateIdentifier = in.readString();
+                in.readMap(credentialInfo, CredentialInfo.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<PerProviderSubscription> CREATOR = new Parcelable.Creator<PerProviderSubscription>() {
+            public PerProviderSubscription createFromParcel(Parcel in) {
+                return new PerProviderSubscription(in);
+            }
+
+            public PerProviderSubscription[] newArray(int size) {
+                return new PerProviderSubscription[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>
+     * This interior node contains the Home SP information, subscription policy, management and credential information.
+     **/
+    public static class CredentialInfo implements Parcelable {
+        public String nodeName;
+        public Policy policy = new Policy();
+        public String credentialPriority;
+        public HashMap<String, AAAServerTrustRoot> aAAServerTrustRoot = new HashMap<String, AAAServerTrustRoot>();
+        public SubscriptionUpdate subscriptionUpdate = new SubscriptionUpdate();
+        public HomeSP homeSP = new HomeSP();
+        public SubscriptionParameters subscriptionParameters = new SubscriptionParameters();
+        public Credential credential = new Credential();
+        public Extension extension = new Extension();
+
+        public CredentialInfo(String nn) {
+            nodeName = nn;
+        }
+
+        public AAAServerTrustRoot createAAAServerTrustRoot(String name, String url, String fp) {
+            AAAServerTrustRoot obj = new AAAServerTrustRoot(name, url, fp);
+            aAAServerTrustRoot.put(name, obj);
+            return obj;
+        }
+
+        public CredentialInfo() {
+        }
+
+        public CredentialInfo(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeParcelable(policy, flags);
+            out.writeString(credentialPriority);
+            out.writeMap(aAAServerTrustRoot);
+            out.writeParcelable(subscriptionUpdate, flags);
+            out.writeParcelable(homeSP, flags);
+            out.writeParcelable(subscriptionParameters, flags);
+            out.writeParcelable(credential, flags);
+            //out.writeParcelable(extension, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                policy = in.readParcelable(Policy.class.getClassLoader());
+                credentialPriority = in.readString();
+                in.readMap(aAAServerTrustRoot, AAAServerTrustRoot.class.getClassLoader());
+                subscriptionUpdate = in.readParcelable(SubscriptionUpdate.class.getClassLoader());
+                homeSP = in.readParcelable(HomeSP.class.getClassLoader());
+                subscriptionParameters = in.readParcelable(SubscriptionParameters.class
+                        .getClassLoader());
+                credential = in.readParcelable(Credential.class.getClassLoader());
+                //extension = in.readParcelable(Extension.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<CredentialInfo> CREATOR = new Parcelable.Creator<CredentialInfo>() {
+            public CredentialInfo createFromParcel(Parcel in) {
+                return new CredentialInfo(in);
+            }
+
+            public CredentialInfo[] newArray(int size) {
+                return new CredentialInfo[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy
+     **/
+    public static class Policy implements Parcelable {
+        public HashMap<String, PreferredRoamingPartnerList> preferredRoamingPartnerList = new HashMap<String, PreferredRoamingPartnerList>();
+        public HashMap<String, MinBackhaulThresholdNetwork> minBackhaulThreshold = new HashMap<String, MinBackhaulThresholdNetwork>();
+        public PolicyUpdate policyUpdate = new PolicyUpdate();
+        public HashMap<String, SPExclusionList> sPExclusionList = new HashMap<String, SPExclusionList>();
+        public HashMap<String, RequiredProtoPortTuple> requiredProtoPortTuple = new HashMap<String, RequiredProtoPortTuple>();
+        public String maximumBSSLoadValue;
+
+        public PreferredRoamingPartnerList createPreferredRoamingPartnerList(String name,
+                String fqdn, String priority, String country) {
+            PreferredRoamingPartnerList obj = new PreferredRoamingPartnerList(name, fqdn, priority,
+                    country);
+            preferredRoamingPartnerList.put(name, obj);
+            return obj;
+        }
+
+        public MinBackhaulThresholdNetwork createMinBackhaulThreshold(String name, String type,
+                String dl, String ul) {
+            MinBackhaulThresholdNetwork obj = new MinBackhaulThresholdNetwork(name, type, dl, ul);
+            minBackhaulThreshold.put(name, obj);
+            return obj;
+        }
+
+        public SPExclusionList createSPExclusionList(String name, String ssid) {
+            SPExclusionList obj = new SPExclusionList(name, ssid);
+            sPExclusionList.put(name, obj);
+            return obj;
+        }
+
+        public RequiredProtoPortTuple createRequiredProtoPortTuple(String name, String proto,
+                String port) {
+            RequiredProtoPortTuple obj = new RequiredProtoPortTuple(name, proto, port);
+            requiredProtoPortTuple.put(name, obj);
+            return obj;
+        }
+
+        public Policy() {
+        }
+
+        public Policy(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeMap(preferredRoamingPartnerList);
+            out.writeMap(minBackhaulThreshold);
+            out.writeParcelable(policyUpdate, flags);
+            out.writeMap(sPExclusionList);
+            out.writeMap(requiredProtoPortTuple);
+            out.writeString(maximumBSSLoadValue);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                in.readMap(preferredRoamingPartnerList,
+                        PreferredRoamingPartnerList.class.getClassLoader());
+                in.readMap(minBackhaulThreshold, MinBackhaulThresholdNetwork.class.getClassLoader());
+                policyUpdate = in.readParcelable(PolicyUpdate.class.getClassLoader());
+                in.readMap(sPExclusionList, SPExclusionList.class.getClassLoader());
+                in.readMap(requiredProtoPortTuple, RequiredProtoPortTuple.class.getClassLoader());
+                maximumBSSLoadValue = in.readString();
+
+            }
+        }
+
+        public static final Parcelable.Creator<Policy> CREATOR = new Parcelable.Creator<Policy>() {
+            public Policy createFromParcel(Parcel in) {
+                return new Policy(in);
+            }
+
+            public Policy[] newArray(int size) {
+                return new Policy[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>
+     **/
+    public static class PreferredRoamingPartnerList implements Parcelable {
+        public String nodeName;
+        public String FQDN_Match; //maximum 255 + ",includeSubdomains", equals 273
+        public String Priority;
+        public String Country; // maximum 600 octets
+
+        public PreferredRoamingPartnerList(String nn, String f, String p, String c) {
+            nodeName = nn;
+            FQDN_Match = f;
+            Priority = p;
+            Country = c;
+        }
+
+        public PreferredRoamingPartnerList() {
+        }
+
+        public PreferredRoamingPartnerList(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(FQDN_Match);
+            out.writeString(Priority);
+            out.writeString(Country);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                FQDN_Match = in.readString();
+                Priority = in.readString();
+                Country = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<PreferredRoamingPartnerList> CREATOR = new Parcelable.Creator<PreferredRoamingPartnerList>() {
+            public PreferredRoamingPartnerList createFromParcel(Parcel in) {
+                return new PreferredRoamingPartnerList(in);
+            }
+
+            public PreferredRoamingPartnerList[] newArray(int size) {
+                return new PreferredRoamingPartnerList[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/MinBackhaulThreshold
+     **/
+    public static class MinBackhaulThresholdNetwork implements Parcelable {
+        public String nodeName;
+        public String NetworkType;
+        public String DLBandwidth;
+        public String ULBandwidth;
+
+        public MinBackhaulThresholdNetwork(String nn, String nt, String d, String u) {
+            nodeName = nn;
+            NetworkType = nt;
+            DLBandwidth = d;
+            ULBandwidth = u;
+        }
+
+        public MinBackhaulThresholdNetwork() {
+        }
+
+        public MinBackhaulThresholdNetwork(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(NetworkType);
+            out.writeString(DLBandwidth);
+            out.writeString(ULBandwidth);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                NetworkType = in.readString();
+                DLBandwidth = in.readString();
+                ULBandwidth = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<MinBackhaulThresholdNetwork> CREATOR = new Parcelable.Creator<MinBackhaulThresholdNetwork>() {
+            public MinBackhaulThresholdNetwork createFromParcel(Parcel in) {
+                return new MinBackhaulThresholdNetwork(in);
+            }
+
+            public MinBackhaulThresholdNetwork[] newArray(int size) {
+                return new MinBackhaulThresholdNetwork[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/PolicyUpdate
+     **/
+    public static class PolicyUpdate implements Parcelable {
+        public String UpdateInterval;
+        public String UpdateMethod;
+        public String Restriction;
+        public String URI;
+        public UsernamePassword usernamePassword = new UsernamePassword();
+        public String Other;
+        public TrustRoot trustRoot = new TrustRoot();
+
+        public PolicyUpdate() {
+        }
+
+        public PolicyUpdate(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(UpdateInterval);
+            out.writeString(UpdateMethod);
+            out.writeString(Restriction);
+            out.writeString(URI);
+            out.writeParcelable(usernamePassword, flags);
+            out.writeString(Other);
+            out.writeParcelable(trustRoot, flags);
+
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                UpdateInterval = in.readString();
+                UpdateMethod = in.readString();
+                Restriction = in.readString();
+                URI = in.readString();
+                usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+                Other = in.readString();
+                trustRoot = in.readParcelable(TrustRoot.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<PolicyUpdate> CREATOR = new Parcelable.Creator<PolicyUpdate>() {
+            public PolicyUpdate createFromParcel(Parcel in) {
+                return new PolicyUpdate(in);
+            }
+
+            public PolicyUpdate[] newArray(int size) {
+                return new PolicyUpdate[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/SPExclusionList
+     **/
+    public static class SPExclusionList implements Parcelable {
+        public String nodeName;
+        public String SSID;
+
+        public SPExclusionList(String nn, String s) {
+            nodeName = nn;
+            SSID = s;
+        }
+
+        public SPExclusionList() {
+        }
+
+        public SPExclusionList(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(SSID);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                SSID = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<SPExclusionList> CREATOR = new Parcelable.Creator<SPExclusionList>() {
+            public SPExclusionList createFromParcel(Parcel in) {
+                return new SPExclusionList(in);
+            }
+
+            public SPExclusionList[] newArray(int size) {
+                return new SPExclusionList[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/RequiredProtoPortTuple
+     **/
+    public static class RequiredProtoPortTuple implements Parcelable {
+        public String nodeName;
+        public String IPProtocol;
+        public String PortNumber;
+
+        public RequiredProtoPortTuple() {
+        }
+
+        public RequiredProtoPortTuple(String nn, String protocol, String port) {
+            nodeName = nn;
+            IPProtocol = protocol;
+            PortNumber = port;
+        }
+
+        public RequiredProtoPortTuple(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(IPProtocol);
+            out.writeString(PortNumber);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                IPProtocol = in.readString();
+                PortNumber = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<RequiredProtoPortTuple> CREATOR = new Parcelable.Creator<RequiredProtoPortTuple>() {
+            public RequiredProtoPortTuple createFromParcel(Parcel in) {
+                return new RequiredProtoPortTuple(in);
+            }
+
+            public RequiredProtoPortTuple[] newArray(int size) {
+                return new RequiredProtoPortTuple[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/AAAServerTrustRoot
+     **/
+    public static class AAAServerTrustRoot implements Parcelable {
+        public String nodeName;
+        public String CertURL;
+        public String CertSHA256Fingerprint;
+
+        public AAAServerTrustRoot(String nn, String url, String fp) {
+            nodeName = nn;
+            CertURL = url;
+            CertSHA256Fingerprint = fp;
+        }
+
+        public AAAServerTrustRoot() {
+        }
+
+        public AAAServerTrustRoot(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(CertURL);
+            out.writeString(CertSHA256Fingerprint);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                CertURL = in.readString();
+                CertSHA256Fingerprint = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<AAAServerTrustRoot> CREATOR = new Parcelable.Creator<AAAServerTrustRoot>() {
+            public AAAServerTrustRoot createFromParcel(Parcel in) {
+                return new AAAServerTrustRoot(in);
+            }
+
+            public AAAServerTrustRoot[] newArray(int size) {
+                return new AAAServerTrustRoot[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/SubscriptionUpdate
+     **/
+    public static class SubscriptionUpdate implements Parcelable {
+        public String UpdateInterval;
+        public String UpdateMethod;
+        public String Restriction;
+        public String URI;
+        public UsernamePassword usernamePassword = new UsernamePassword();
+        public String Other;
+        public TrustRoot trustRoot = new TrustRoot();
+
+        public SubscriptionUpdate() {
+        }
+
+        public SubscriptionUpdate(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(UpdateInterval);
+            out.writeString(UpdateMethod);
+            out.writeString(Restriction);
+            out.writeString(URI);
+            out.writeParcelable(usernamePassword, flags);
+            out.writeString(Other);
+            out.writeParcelable(trustRoot, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                UpdateInterval = in.readString();
+                UpdateMethod = in.readString();
+                Restriction = in.readString();
+                URI = in.readString();
+                usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+                Other = in.readString();
+                trustRoot = in.readParcelable(TrustRoot.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<SubscriptionUpdate> CREATOR = new Parcelable.Creator<SubscriptionUpdate>() {
+            public SubscriptionUpdate createFromParcel(Parcel in) {
+                return new SubscriptionUpdate(in);
+            }
+
+            public SubscriptionUpdate[] newArray(int size) {
+                return new SubscriptionUpdate[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/PolicyUpdate/TrustRoot
+     * PerProviderSubscription/<X+>/SubscriptionUpdate/TrustRoot
+     * PerProviderSubscription/<X+>/AAAServerTrustRoot/<X+>
+     **/
+    public static class TrustRoot implements Parcelable {
+        public String CertURL;
+        public String CertSHA256Fingerprint;
+
+        public TrustRoot() {
+        }
+
+        public TrustRoot(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(CertURL);
+            out.writeString(CertSHA256Fingerprint);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                CertURL = in.readString();
+                CertSHA256Fingerprint = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<TrustRoot> CREATOR = new Parcelable.Creator<TrustRoot>() {
+            public TrustRoot createFromParcel(Parcel in) {
+                return new TrustRoot(in);
+            }
+
+            public TrustRoot[] newArray(int size) {
+                return new TrustRoot[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/PolicyUpdate/UsernamePassword
+     * PerProviderSubscription/<X+>/SubscriptionUpdate/UsernamePassword
+     * PerProviderSubscription/<X+>/Credential/UsernamePassword
+     **/
+    public static class UsernamePassword implements Parcelable {
+        public String Username;
+        public String Password;
+        //following are Credential node used only
+        public boolean MachineManaged;
+        public String SoftTokenApp;
+        public String AbleToShare;
+        public EAPMethod eAPMethod = new EAPMethod();
+
+        public UsernamePassword() {
+        }
+
+        public UsernamePassword(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(Username);
+            out.writeString(Password);
+            out.writeInt(MachineManaged ? 1 : 0);
+            out.writeString(SoftTokenApp);
+            out.writeString(AbleToShare);
+            out.writeParcelable(eAPMethod, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                Username = in.readString();
+                Password = in.readString();
+                MachineManaged = (in.readInt() == 1) ? true : false;
+                SoftTokenApp = in.readString();
+                AbleToShare = in.readString();
+                eAPMethod = in.readParcelable(EAPMethod.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<UsernamePassword> CREATOR = new Parcelable.Creator<UsernamePassword>() {
+            public UsernamePassword createFromParcel(Parcel in) {
+                return new UsernamePassword(in);
+            }
+
+            public UsernamePassword[] newArray(int size) {
+                return new UsernamePassword[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Credential/UsernamePassword/EAPMethod
+     **/
+    public static class EAPMethod implements Parcelable {
+        public String EAPType;
+        public String VendorId;
+        public String VendorType;
+        public String InnerEAPType;
+        public String InnerVendorId;
+        public String InnerVendorType;
+        public String InnerMethod;
+
+        public EAPMethod() {
+        }
+
+        public EAPMethod(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(EAPType);
+            out.writeString(VendorId);
+            out.writeString(VendorType);
+            out.writeString(InnerEAPType);
+            out.writeString(InnerVendorId);
+            out.writeString(InnerVendorType);
+            out.writeString(InnerMethod);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                EAPType = in.readString();
+                VendorId = in.readString();
+                VendorType = in.readString();
+                InnerEAPType = in.readString();
+                InnerVendorId = in.readString();
+                InnerVendorType = in.readString();
+                InnerMethod = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<EAPMethod> CREATOR = new Parcelable.Creator<EAPMethod>() {
+            public EAPMethod createFromParcel(Parcel in) {
+                return new EAPMethod(in);
+            }
+
+            public EAPMethod[] newArray(int size) {
+                return new EAPMethod[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/HomeSP
+     **/
+    public static class HomeSP implements Parcelable {
+        public HashMap<String, NetworkID> networkID = new HashMap<String, NetworkID>();
+        public String FriendlyName;
+        public String IconURL;
+        public String FQDN;
+        public HashMap<String, HomeOIList> homeOIList = new HashMap<String, HomeOIList>();
+        public HashMap<String, OtherHomePartners> otherHomePartners = new HashMap<String, OtherHomePartners>();
+        public String RoamingConsortiumOI;
+
+        public NetworkID createNetworkID(String name, String ssid, String hessid) {
+            NetworkID obj = new NetworkID(name, ssid, hessid);
+            networkID.put(name, obj);
+            return obj;
+        }
+
+        public HomeOIList createHomeOIList(String name, String homeoi, boolean required) {
+            HomeOIList obj = new HomeOIList(name, homeoi, required);
+            homeOIList.put(name, obj);
+            return obj;
+        }
+
+        public OtherHomePartners createOtherHomePartners(String name, String fqdn) {
+            OtherHomePartners obj = new OtherHomePartners(name, fqdn);
+            otherHomePartners.put(name, obj);
+            return obj;
+        }
+
+        public HomeSP() {
+        }
+
+        public HomeSP(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeMap(networkID);
+            out.writeString(FriendlyName);
+            out.writeString(IconURL);
+            out.writeString(FQDN);
+            out.writeMap(homeOIList);
+            out.writeMap(otherHomePartners);
+            out.writeString(RoamingConsortiumOI);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                in.readMap(networkID, NetworkID.class.getClassLoader());
+                FriendlyName = in.readString();
+                IconURL = in.readString();
+                FQDN = in.readString();
+                in.readMap(homeOIList, HomeOIList.class.getClassLoader());
+                in.readMap(otherHomePartners, OtherHomePartners.class.getClassLoader());
+                RoamingConsortiumOI = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<HomeSP> CREATOR = new Parcelable.Creator<HomeSP>() {
+            public HomeSP createFromParcel(Parcel in) {
+                return new HomeSP(in);
+            }
+
+            public HomeSP[] newArray(int size) {
+                return new HomeSP[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/HomeSP/NetworkID
+     **/
+    public static class NetworkID implements Parcelable {
+        public String nodeName;
+        public String SSID;
+        public String HESSID;
+
+        public NetworkID(String nn, String s, String h) {
+            nodeName = nn;
+            SSID = s;
+            HESSID = h;
+        }
+
+        public NetworkID() {
+        }
+
+        public NetworkID(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(SSID);
+            out.writeString(HESSID);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                SSID = in.readString();
+                HESSID = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<NetworkID> CREATOR = new Parcelable.Creator<NetworkID>() {
+            public NetworkID createFromParcel(Parcel in) {
+                return new NetworkID(in);
+            }
+
+            public NetworkID[] newArray(int size) {
+                return new NetworkID[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/HomeSP/HomeOIList
+     **/
+    public static class HomeOIList implements Parcelable {
+        public String nodeName;
+        public String HomeOI;
+        public boolean HomeOIRequired;
+
+        public HomeOIList(String nn, String h, boolean r) {
+            nodeName = nn;
+            HomeOI = h;
+            HomeOIRequired = r;
+        }
+
+        public HomeOIList() {
+        }
+
+        public HomeOIList(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(HomeOI);
+            out.writeInt(HomeOIRequired ? 1 : 0);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                HomeOI = in.readString();
+                HomeOIRequired = (in.readInt() == 1) ? true : false;
+            }
+        }
+
+        public static final Parcelable.Creator<HomeOIList> CREATOR = new Parcelable.Creator<HomeOIList>() {
+            public HomeOIList createFromParcel(Parcel in) {
+                return new HomeOIList(in);
+            }
+
+            public HomeOIList[] newArray(int size) {
+                return new HomeOIList[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/HomeSP/OtherHomePartners
+     **/
+    public static class OtherHomePartners implements Parcelable {
+        public String nodeName;
+        public String FQDN;
+
+        public OtherHomePartners(String nn, String f) {
+            nodeName = nn;
+            FQDN = f;
+        }
+
+        public OtherHomePartners() {
+        }
+
+        public OtherHomePartners(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(FQDN);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                FQDN = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<OtherHomePartners> CREATOR = new Parcelable.Creator<OtherHomePartners>() {
+            public OtherHomePartners createFromParcel(Parcel in) {
+                return new OtherHomePartners(in);
+            }
+
+            public OtherHomePartners[] newArray(int size) {
+                return new OtherHomePartners[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/SubscriptionParameters
+     **/
+    public static class SubscriptionParameters implements Parcelable {
+        public String CreationDate;
+        public String ExpirationDate;
+        public String TypeOfSubscription;
+        public UsageLimits usageLimits = new UsageLimits();
+
+        public SubscriptionParameters() {
+        }
+
+        public SubscriptionParameters(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(CreationDate);
+            out.writeString(ExpirationDate);
+            out.writeString(TypeOfSubscription);
+            out.writeParcelable(usageLimits, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                CreationDate = in.readString();
+                ExpirationDate = in.readString();
+                TypeOfSubscription = in.readString();
+                usageLimits = in.readParcelable(UsageLimits.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<SubscriptionParameters> CREATOR = new Parcelable.Creator<SubscriptionParameters>() {
+            public SubscriptionParameters createFromParcel(Parcel in) {
+                return new SubscriptionParameters(in);
+            }
+
+            public SubscriptionParameters[] newArray(int size) {
+                return new SubscriptionParameters[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/SubscriptionParameters/UsageLimits
+     **/
+    public static class UsageLimits implements Parcelable {
+        public String DataLimit;
+        public String StartDate;
+        public String TimeLimit;
+        public String UsageTimePeriod;
+
+        public UsageLimits() {
+        }
+
+        public UsageLimits(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(DataLimit);
+            out.writeString(StartDate);
+            out.writeString(TimeLimit);
+            out.writeString(UsageTimePeriod);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                DataLimit = in.readString();
+                StartDate = in.readString();
+                TimeLimit = in.readString();
+                UsageTimePeriod = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<UsageLimits> CREATOR = new Parcelable.Creator<UsageLimits>() {
+            public UsageLimits createFromParcel(Parcel in) {
+                return new UsageLimits(in);
+            }
+
+            public UsageLimits[] newArray(int size) {
+                return new UsageLimits[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Credential
+     **/
+    public static class Credential implements Parcelable {
+        public String CreationDate;
+        public String ExpirationDate;
+        public UsernamePassword usernamePassword = new UsernamePassword();
+        public DigitalCertificate digitalCertificate = new DigitalCertificate();
+        public String Realm;
+        public boolean CheckAAAServerCertStatus;
+        public SIM sim = new SIM();
+
+        public Credential() {
+        }
+
+        public Credential(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(CreationDate);
+            out.writeString(ExpirationDate);
+            out.writeParcelable(usernamePassword, flags);
+            out.writeParcelable(digitalCertificate, flags);
+            out.writeString(Realm);
+            out.writeInt(CheckAAAServerCertStatus ? 1 : 0);
+            out.writeParcelable(sim, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                CreationDate = in.readString();
+                ExpirationDate = in.readString();
+                usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+                digitalCertificate = in.readParcelable(DigitalCertificate.class.getClassLoader());
+                Realm = in.readString();
+                CheckAAAServerCertStatus = (in.readInt() == 1) ? true : false;
+                sim = in.readParcelable(SIM.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<Credential> CREATOR = new Parcelable.Creator<Credential>() {
+            public Credential createFromParcel(Parcel in) {
+                return new Credential(in);
+            }
+
+            public Credential[] newArray(int size) {
+                return new Credential[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Credential/DigitalCertificate
+     **/
+    public static class DigitalCertificate implements Parcelable {
+        public String CertificateType;
+        public String CertSHA256Fingerprint;
+
+        public DigitalCertificate() {
+        }
+
+        public DigitalCertificate(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(CertificateType);
+            out.writeString(CertSHA256Fingerprint);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                CertificateType = in.readString();
+                CertSHA256Fingerprint = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<DigitalCertificate> CREATOR = new Parcelable.Creator<DigitalCertificate>() {
+            public DigitalCertificate createFromParcel(Parcel in) {
+                return new DigitalCertificate(in);
+            }
+
+            public DigitalCertificate[] newArray(int size) {
+                return new DigitalCertificate[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Credential/SIM
+     **/
+    public static class SIM implements Parcelable {
+        public String IMSI;
+        public String EAPType;
+
+        public SIM() {
+        }
+
+        public SIM(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(IMSI);
+            out.writeString(EAPType);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                IMSI = in.readString();
+                EAPType = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<SIM> CREATOR = new Parcelable.Creator<SIM>() {
+            public SIM createFromParcel(Parcel in) {
+                return new SIM(in);
+            }
+
+            public SIM[] newArray(int size) {
+                return new SIM[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Extension
+     **/
+    public static class Extension {
+        public String empty;
+    }
+
+    public WifiPasspointDmTree() {
+    }
+
+    public WifiPasspointDmTree(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeMap(spFqdn);
+    }
+
+    public void readFromParcel(Parcel in) {
+        if (in == null) {
+            //log here
+        } else {
+            in.readMap(spFqdn, SpFqdn.class.getClassLoader());
+        }
+    }
+
+    public static final Parcelable.Creator<WifiPasspointDmTree> CREATOR = new Parcelable.Creator<WifiPasspointDmTree>() {
+        public WifiPasspointDmTree createFromParcel(Parcel in) {
+            return new WifiPasspointDmTree(in);
+        }
+
+        public WifiPasspointDmTree[] newArray(int size) {
+            return new WifiPasspointDmTree[size];
+        }
+    };
+
+}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
similarity index 95%
copy from wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
copy to wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
index cc11045..27f23bc 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.passpoint;
 
-parcelable PasspointInfo;
+parcelable WifiPasspointInfo;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
new file mode 100644
index 0000000..99bea2f
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
@@ -0,0 +1,285 @@
+/*
+ * 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;
+
+/** @hide */
+public class WifiPasspointInfo 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<WifiPasspointOsuProvider> osuProviderList;
+
+    /** default constructor @hide */
+    public WifiPasspointInfo() {
+        //        osuProviderList = new ArrayList<OsuProvider>();
+    }
+
+    /** copy constructor @hide */
+    public WifiPasspointInfo(WifiPasspointInfo 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<WifiPasspointOsuProvider>();
+            for (WifiPasspointOsuProvider osu : source.osuProviderList)
+                osuProviderList.add(new WifiPasspointOsuProvider(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 (WifiPasspointOsuProvider 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<WifiPasspointInfo> CREATOR =
+            new Parcelable.Creator<WifiPasspointInfo>() {
+                @Override
+                public WifiPasspointInfo createFromParcel(Parcel in) {
+                    WifiPasspointInfo p = new WifiPasspointInfo();
+                    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<WifiPasspointOsuProvider>();
+                        for (int i = 0; i < n; i++) {
+                            WifiPasspointOsuProvider osu = WifiPasspointOsuProvider.CREATOR
+                                    .createFromParcel(in);
+                            p.osuProviderList.add(osu);
+                        }
+                    }
+                    return p;
+                }
+
+                @Override
+                public WifiPasspointInfo[] newArray(int size) {
+                    return new WifiPasspointInfo[size];
+                }
+            };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointManager.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
similarity index 75%
rename from wifi/java/android/net/wifi/passpoint/PasspointManager.java
rename to wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
index 234a44c..ee4dc5a 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointManager.java
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
@@ -34,9 +34,9 @@
 import java.util.List;
 
 /**
- * TODO: doc
+ * Provides APIs for managing Wifi Passpoint credentials.
  */
-public class PasspointManager {
+public class WifiPasspointManager {
 
     private static final String TAG = "PasspointManager";
 
@@ -44,37 +44,58 @@
 
     /* 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 in an known state. This should only occur in boot time @hide */
+    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 disabled. This occurs when wifi is disabled. @hide */
+    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 discovery state. @hide */
+    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 access state. @hide */
+    public static final int PASSPOINT_STATE_ACCESS = 3;
 
-    /** Passpoint is enabled and in provisioning state. */
-    public static final int PASSPOINT_STATE_PROVISION   = 4;
+    /** Passpoint is enabled and in provisioning state. @hide */
+    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 due to an internal error @hide */
+    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 wifi is disabled @hide */
+    public static final int WIFI_DISABLED = 1;
 
-    /** Indicates that the operation failed because the framework is busy */
-    public static final int BUSY            = 2;
+    /** Indicates that the operation failed because the framework is busy @hide */
+    public static final int BUSY = 2;
+
+    /**
+     * protocol supported for Passpoint
+     * @hide
+     */
+    public static final String PROTOCOL_DM = "OMA-DM-ClientInitiated";
+
+    /**
+     * protocol supported for Passpoint
+     * @hide
+     */
+    public static final String PROTOCOL_SOAP = "SPP-ClientInitiated";
 
     /* Passpoint broadcasts */
 
     /**
+     * Broadcast intent action indicating that Passpoint online sign up is
+     * avaiable.
+     * @hide
+     */
+    public static final String PASSPOINT_OSU_AVAILABLE =
+            "android.net.wifi.passpoint.OSU_AVAILABLE";
+
+    /**
      * Broadcast intent action indicating that the state of Passpoint
      * connectivity has changed
+     * @hide
      */
     public static final String PASSPOINT_STATE_CHANGED_ACTION =
             "android.net.wifi.passpoint.STATE_CHANGE";
@@ -82,6 +103,7 @@
     /**
      * Broadcast intent action indicating that the saved Passpoint credential
      * list has changed
+     * @hide
      */
     public static final String PASSPOINT_CRED_CHANGED_ACTION =
             "android.net.wifi.passpoint.CRED_CHANGE";
@@ -101,9 +123,9 @@
     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
+     * @hide
      */
     public interface ChannelListener {
         /**
@@ -115,6 +137,7 @@
 
     /**
      * Interface for callback invocation on an application action
+     * @hide
      */
     public interface ActionListener {
         /** The operation succeeded */
@@ -163,6 +186,7 @@
      * 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}
+     * @hide
      */
     public static class Channel {
         private final static int INVALID_LISTENER_KEY = 0;
@@ -193,7 +217,8 @@
         }
 
         private int putListener(Object listener, int count) {
-            if (listener == null || count <= 0) return INVALID_LISTENER_KEY;
+            if (listener == null || count <= 0)
+                return INVALID_LISTENER_KEY;
             int key;
             synchronized (mListenerMapLock) {
                 do {
@@ -207,13 +232,15 @@
 
         private Object getListener(int key, boolean force) {
             Log.d(TAG, "getListener() key=" + key + " force=" + force);
-            if (key == INVALID_LISTENER_KEY) return null;
+            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;
+                    if (count > 0)
+                        return null;
                 }
                 Log.d(TAG, "remove key");
                 mListenerMapCount.remove(key);
@@ -223,12 +250,14 @@
 
         private void anqpRequestStart(ScanResult sr) {
             Log.d(TAG, "anqpRequestStart sr.bssid=" + sr.BSSID);
-            synchronized(mAnqpRequestLock) { mAnqpRequest.add(sr); }
+            synchronized (mAnqpRequestLock) {
+                mAnqpRequest.add(sr);
+            }
         }
 
-        private void anqpRequestFinish(PasspointInfo result) {
+        private void anqpRequestFinish(WifiPasspointInfo result) {
             Log.d(TAG, "anqpRequestFinish pi.bssid=" + result.bssid);
-            synchronized(mAnqpRequestLock) {
+            synchronized (mAnqpRequestLock) {
                 for (ScanResult sr : mAnqpRequest)
                     if (sr.BSSID.equals(result.bssid)) {
                         Log.d(TAG, "find hit " + result.bssid);
@@ -242,7 +271,7 @@
 
         private void anqpRequestFinish(ScanResult sr) {
             Log.d(TAG, "anqpRequestFinish sr.bssid=" + sr.BSSID);
-            synchronized(mAnqpRequestLock) {
+            synchronized (mAnqpRequestLock) {
                 for (ScanResult sr1 : mAnqpRequest)
                     if (sr1.BSSID.equals(sr.BSSID)) {
                         mAnqpRequest.remove(sr1);
@@ -268,7 +297,7 @@
                         break;
 
                     case REQUEST_ANQP_INFO_SUCCEEDED:
-                        PasspointInfo result = (PasspointInfo) message.obj;
+                        WifiPasspointInfo result = (WifiPasspointInfo) message.obj;
                         anqpRequestFinish(result);
                         if (listener != null) {
                             ((ActionListener) listener).onSuccess();
@@ -277,7 +306,8 @@
 
                     case REQUEST_ANQP_INFO_FAILED:
                         anqpRequestFinish((ScanResult) message.obj);
-                        if (listener == null) getListener(message.arg2, true);
+                        if (listener == null)
+                            getListener(message.arg2, true);
                         if (listener != null) {
                             ((ActionListener) listener).onFailure(message.arg1);
                         }
@@ -292,38 +322,36 @@
 
     }
 
-
     private static final int BASE = Protocol.BASE_WIFI_PASSPOINT_MANAGER;
 
     /** @hide */
-    public static final int REQUEST_ANQP_INFO                       = BASE + 1;
+    public static final int REQUEST_ANQP_INFO = BASE + 1;
 
     /** @hide */
-    public static final int REQUEST_ANQP_INFO_FAILED                = BASE + 2;
+    public static final int REQUEST_ANQP_INFO_FAILED = BASE + 2;
 
     /** @hide */
-    public static final int REQUEST_ANQP_INFO_SUCCEEDED             = BASE + 3;
+    public static final int REQUEST_ANQP_INFO_SUCCEEDED = BASE + 3;
 
     /** @hide */
-    public static final int REQUEST_OSU_INFO                        = BASE + 4;
+    public static final int REQUEST_OSU_INFO = BASE + 4;
 
     /** @hide */
-    public static final int REQUEST_OSU_INFO_FAILED                 = BASE + 5;
+    public static final int REQUEST_OSU_INFO_FAILED = BASE + 5;
 
     /** @hide */
-    public static final int REQUEST_OSU_INFO_SUCCEEDED              = BASE + 6;
-
+    public static final int REQUEST_OSU_INFO_SUCCEEDED = BASE + 6;
 
     private Context mContext;
-    IPasspointManager mService;
-
+    IWifiPasspointManager mService;
 
     /**
      * TODO: doc
      * @param context
      * @param service
+     * @hide
      */
-    public PasspointManager(Context context, IPasspointManager service) {
+    public WifiPasspointManager(Context context, IWifiPasspointManager service) {
         mContext = context;
         mService = service;
     }
@@ -338,10 +366,13 @@
      *            null.
      * @return Channel instance that is necessary for performing any further
      *         passpoint operations
+     *
+     * @hide
      */
     public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
         Messenger messenger = getMessenger();
-        if (messenger == null) return null;
+        if (messenger == null)
+            return null;
 
         Channel c = new Channel(srcContext, srcLooper, listener);
         if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
@@ -366,49 +397,33 @@
         }
     }
 
-    /**
-     * 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}
-     */
+    /** @hide */
     public int getPasspointState() {
-        try{
+        try {
             return mService.getPasspointState();
-        }
-        catch (RemoteException e) {
+        } catch (RemoteException e) {
             return PASSPOINT_STATE_UNKNOWN;
         }
     }
 
-    /**
-     * TODO: doc
-     *
-     * @param c
-     * @param requested
-     * @param mask
-     * @param listener
-     *
-     * @hide
-     */
+    /** @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);
-        }
+        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");
+            if (DBG)
+                Log.d(TAG, "ANQP info request contains no HS20 APs, skipped");
             listener.onSuccess();
             return;
         }
@@ -418,25 +433,13 @@
         Log.d(TAG, "requestAnqpInfo end");
     }
 
-    /**
-     * TODO: doc
-     *
-     * @param c
-     * @param requested
-     * @param resolution
-     * @param listener
-     */
-    public void requestOsuIcons(Channel c, List<PasspointOsuProvider> requested,
+    /** @hide */
+    public void requestOsuIcons(Channel c, List<WifiPasspointOsuProvider> requested,
             int resolution, ActionListener listener) {
     }
 
-    /**
-     * TODO: doc
-     *
-     * @param requested
-     * @return
-     */
-    public List<PasspointPolicy> requestCredentialMatch(List<ScanResult> requested) {
+    /** @hide */
+    public List<WifiPasspointPolicy> requestCredentialMatch(List<ScanResult> requested) {
         return null;
     }
 
@@ -447,7 +450,7 @@
      *
      * @return The list of credentials
      */
-    public List<PasspointCredential> getSavedCredentials() {
+    public List<WifiPasspointCredential> getSavedCredentials() {
         return null;
     }
 
@@ -457,32 +460,34 @@
      * @param cred The credential to be added
      * @return {@code true} if the operation succeeds, {@code false} otherwise
      */
-    public boolean addCredential(PasspointCredential cred) {
+    public boolean addCredential(WifiPasspointCredential cred) {
         return true;
     }
 
     /**
-     * Update an existing Passpoint credential.
+     * Update an existing Passpoint credential. Only system or the owner of this
+     * credential has the permission to do this.
      *
      * @param cred The credential to be updated
      * @return {@code true} if the operation succeeds, {@code false} otherwise
      */
-    public boolean updateCredential(PasspointCredential cred) {
+    public boolean updateCredential(WifiPasspointCredential cred) {
         return true;
     }
 
     /**
-     * Remove an existing Passpoint credential.
+     * Remove an existing Passpoint credential. Only system or the owner of this
+     * credential has the permission to do this.
      *
      * @param cred The credential to be removed
      * @return {@code true} if the operation succeeds, {@code false} otherwise
      */
-    public boolean removeCredential(PasspointCredential cred) {
+    public boolean removeCredential(WifiPasspointCredential cred) {
         return true;
     }
 
     /** @hide */
-    public void startOsu(Channel c, PasspointOsuProvider selected, OsuRemListener listener) {
+    public void startOsu(Channel c, WifiPasspointOsuProvider selected, OsuRemListener listener) {
 
     }
 
@@ -490,15 +495,12 @@
     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) {
+    /** @hide */
+    public void connect(WifiPasspointPolicy selected) {
     }
 
     private static void checkChannel(Channel c) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        if (c == null)
+            throw new IllegalArgumentException("Channel needs to be initialized");
     }
 }
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
similarity index 94%
copy from wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
copy to wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
index f5ecb7c..088136f 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.passpoint;
 
-parcelable PasspointOsuProvider;
+parcelable WifiPasspointOsuProvider;
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
similarity index 60%
rename from wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java
rename to wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
index 80d5315..18a8f1e 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointOsuProvider.java
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
@@ -19,18 +19,22 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-/**
- * TODO: doc
- */
-public class PasspointOsuProvider implements Parcelable {
+/** @hide */
+public class WifiPasspointOsuProvider implements Parcelable {
 
-    /** TODO: doc */
+    /** TODO: doc
+     * @hide
+     */
     public static final int OSU_METHOD_UNKNOWN = -1;
 
-    /** TODO: doc */
+    /** TODO: doc
+     * @hide
+     */
     public static final int OSU_METHOD_OMADM = 0;
 
-    /** TODO: doc */
+    /** TODO: doc
+     * @hide
+     */
     public static final int OSU_METHOD_SOAP = 1;
 
     /** TODO: doc */
@@ -39,10 +43,14 @@
     /** TODO: doc */
     public String friendlyName;
 
-    /** TODO: doc */
+    /** TODO: doc
+     * @hide
+     */
     public String serverUri;
 
-    /** TODO: doc */
+    /** TODO: doc
+     * @hide
+     */
     public int osuMethod = OSU_METHOD_UNKNOWN;
 
     /** TODO: doc */
@@ -66,14 +74,13 @@
     /** TODO: doc */
     public String osuService;
 
-
     /** default constructor @hide */
-    public PasspointOsuProvider() {
+    public WifiPasspointOsuProvider() {
         // TODO
     }
 
     /** copy constructor @hide */
-    public PasspointOsuProvider(PasspointOsuProvider source) {
+    public WifiPasspointOsuProvider(WifiPasspointOsuProvider source) {
         // TODO
     }
 
@@ -88,9 +95,9 @@
         sb.append(" osuMethod: ").append(osuMethod);
         if (iconFileName != null) {
             sb.append(" icon: [").append(iconWidth).append("x")
-              .append(iconHeight).append(" ")
-              .append(iconType).append(" ")
-              .append(iconFileName);
+                    .append(iconHeight).append(" ")
+                    .append(iconType).append(" ")
+                    .append(iconFileName);
         }
         if (osuNai != null)
             sb.append(" osuNai: ").append(osuNai);
@@ -119,27 +126,27 @@
         // 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;
-        }
+    public static final Parcelable.Creator<WifiPasspointOsuProvider> CREATOR =
+            new Parcelable.Creator<WifiPasspointOsuProvider>() {
+                @Override
+                public WifiPasspointOsuProvider createFromParcel(Parcel in) {
+                    WifiPasspointOsuProvider osu = new WifiPasspointOsuProvider();
+                    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];
-        }
-    };
+                @Override
+                public WifiPasspointOsuProvider[] newArray(int size) {
+                    return new WifiPasspointOsuProvider[size];
+                }
+            };
 }
diff --git a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
similarity index 95%
rename from wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
rename to wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
index cc11045..1d61da0 100644
--- a/wifi/java/android/net/wifi/passpoint/PasspointInfo.aidl
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.passpoint;
 
-parcelable PasspointInfo;
+parcelable WifiPasspointPolicy;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java
new file mode 100644
index 0000000..5f76562
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java
@@ -0,0 +1,226 @@
+/*
+ * 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;
+import android.util.Log;
+
+/** @hide */
+public class WifiPasspointPolicy implements Parcelable {
+
+    private final static String TAG = "PasspointPolicy";
+
+    /** @hide */
+    public static final int HOME_SP = 0;
+
+    /** @hide */
+    public static final int ROAMING_PARTNER = 1;
+
+    /** @hide */
+    public static final int UNRESTRICTED = 2;
+
+    private String mName;
+    private int mSubscriptionPriority;
+    private int mRoamingPriority;
+    private String mBssid;
+    private String mSsid;
+    private WifiPasspointCredential mCredential;
+    private int mRestriction;// Permitted values are "HomeSP", "RoamingPartner", or "Unrestricted"
+    private boolean mIsHomeSp;
+
+    /** @hide */
+    public WifiPasspointPolicy(String name, int priority, String ssid,
+            String bssid, WifiPasspointCredential pc,
+            int restriction, boolean ishomesp) {
+        mName = name;
+        mSubscriptionPriority = priority;
+        //PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>/Priority
+        mRoamingPriority = 128; //default priority value of 128
+        mSsid = ssid;
+        mCredential = pc;
+        mBssid = bssid;
+        mRestriction = restriction;
+        mIsHomeSp = ishomesp;
+    }
+
+    public String getSsid() {
+        return mSsid;
+    }
+
+    /** @hide */
+    public void setBssid(String bssid) {
+        mBssid = bssid;
+    }
+
+    public String getBssid() {
+        return mBssid;
+    }
+
+    /** @hide */
+    public void setRestriction(int r) {
+        mRestriction = r;
+    }
+
+    /** @hide */
+    public int getRestriction() {
+        return mRestriction;
+    }
+
+    /** @hide */
+    public void setHomeSp(boolean b) {
+        mIsHomeSp = b;
+    }
+
+    /** @hide */
+    public boolean getHomeSp() {
+        return mIsHomeSp;
+    }
+
+    /** @hide */
+    public void setCredential(WifiPasspointCredential newCredential) {
+        mCredential = newCredential;
+    }
+
+    public WifiPasspointCredential getCredential() {
+        // TODO: return a copy
+        return mCredential;
+    }
+
+    /** @hide */
+    public void setSubscriptionPriority(int priority) {
+        mSubscriptionPriority = priority;
+    }
+
+    /** @hide */
+    public void setRoamingPriority(int priority) {
+        mRoamingPriority = priority;
+    }
+
+    public int getSubscriptionPriority() {
+        return mSubscriptionPriority;
+    }
+
+    public int getRoamingPriority() {
+        return mRoamingPriority;
+    }
+
+    /** {@inheritDoc} @hide */
+    public int compareTo(WifiPasspointPolicy another) {
+        Log.d(TAG, "this:" + this);
+        Log.d(TAG, "another:" + another);
+
+        if (another == null) {
+            return -1;
+        } else if (this.mIsHomeSp == true && another.getHomeSp() == false) {
+            //home sp priority is higher then roaming
+            Log.d(TAG, "compare HomeSP  first, this is HomeSP, another isn't");
+            return -1;
+        } else if ((this.mIsHomeSp == true && another.getHomeSp() == true)) {
+            Log.d(TAG, "both HomeSP");
+            //if both home sp, compare subscription priority
+            if (this.mSubscriptionPriority < another.getSubscriptionPriority()) {
+                Log.d(TAG, "this priority is higher");
+                return -1;
+            } else if (this.mSubscriptionPriority == another.getSubscriptionPriority()) {
+                Log.d(TAG, "both priorities equal");
+                //if priority still the same, compare name(ssid)
+                if (this.mName.compareTo(another.mName) != 0) {
+                    Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
+                    return this.mName.compareTo(another.mName);
+                }
+                /**
+                 *if name still the same, compare credential
+                 *the device may has two more credentials(TLS,SIM..etc)
+                 *it can associate to one AP(same ssid). so we should compare by credential
+                 */
+                if (this.mCredential != null && another.mCredential != null) {
+                    if (this.mCredential.compareTo(another.mCredential) != 0) {
+                        Log.d(TAG,
+                                "compare mCredential return:" + this.mName.compareTo(another.mName));
+                        return this.mCredential.compareTo(another.mCredential);
+                    }
+                }
+            } else {
+                return 1;
+            }
+        } else if ((this.mIsHomeSp == false && another.getHomeSp() == false)) {
+            Log.d(TAG, "both RoamingSp");
+            //if both roaming sp, compare roaming priority(preferredRoamingPartnerList/<X+>/priority)
+            if (this.mRoamingPriority < another.getRoamingPriority()) {
+                Log.d(TAG, "this priority is higher");
+                return -1;
+            } else if (this.mRoamingPriority == another.getRoamingPriority()) {//priority equals, compare name
+                Log.d(TAG, "both priorities equal");
+                //if priority still the same, compare name(ssid)
+                if (this.mName.compareTo(another.mName) != 0) {
+                    Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
+                    return this.mName.compareTo(another.mName);
+                }
+                //if name still the same, compare credential
+                if (this.mCredential != null && another.mCredential != null) {
+                    if (this.mCredential.compareTo(another.mCredential) != 0) {
+                        Log.d(TAG,
+                                "compare mCredential return:"
+                                        + this.mCredential.compareTo(another.mCredential));
+                        return this.mCredential.compareTo(another.mCredential);
+                    }
+                }
+            } else {
+                return 1;
+            }
+        }
+
+        Log.d(TAG, "both policies equal");
+        return 0;
+    }
+
+    @Override
+    /** @hide */
+    public String toString() {
+        return "PasspointPolicy: name=" + mName + " SubscriptionPriority=" + mSubscriptionPriority +
+                " mRoamingPriority" + mRoamingPriority +
+                " ssid=" + mSsid + " restriction=" + mRestriction +
+                " ishomesp=" + mIsHomeSp + " Credential=" + mCredential;
+    }
+
+    /** 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<WifiPasspointPolicy> CREATOR =
+            new Creator<WifiPasspointPolicy>() {
+                @Override
+                public WifiPasspointPolicy createFromParcel(Parcel in) {
+                    return null;
+                }
+
+                @Override
+                public WifiPasspointPolicy[] newArray(int size) {
+                    return new WifiPasspointPolicy[size];
+                }
+            };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiTree.aidl b/wifi/java/android/net/wifi/passpoint/WifiTree.aidl
deleted file mode 100644
index 8e2fab742..0000000
--- a/wifi/java/android/net/wifi/passpoint/WifiTree.aidl
+++ /dev/null
@@ -1,19 +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.passpoint;
-
-parcelable WifiTree;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiTree.java b/wifi/java/android/net/wifi/passpoint/WifiTree.java
deleted file mode 100644
index 8fdb6e1..0000000
--- a/wifi/java/android/net/wifi/passpoint/WifiTree.java
+++ /dev/null
@@ -1,51 +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.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];

-                }

-            };

-}