Merge "Fix comment for sendData."
diff --git a/Android.mk b/Android.mk
index 43b7e59..efbee5e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -306,6 +306,7 @@
 	media/java/android/media/IRemoteControlDisplay.aidl \
 	media/java/android/media/IRemoteDisplayCallback.aidl \
 	media/java/android/media/IRemoteDisplayProvider.aidl \
+	media/java/android/media/IRemoteVolumeController.aidl \
 	media/java/android/media/IRemoteVolumeObserver.aidl \
 	media/java/android/media/IRingtonePlayer.aidl \
 	media/java/android/media/IVolumeController.aidl \
@@ -330,10 +331,18 @@
 	telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl \
 	telecomm/java/com/android/internal/telecomm/ICallServiceLookupResponse.aidl \
 	telecomm/java/com/android/internal/telecomm/ICallServiceProvider.aidl \
+	telecomm/java/com/android/internal/telecomm/ICallVideoProvider.aidl \
 	telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl \
 	telecomm/java/com/android/internal/telecomm/IInCallService.aidl \
 	telecomm/java/com/android/internal/telecomm/ITelecommService.aidl \
 	telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl \
+	telephony/java/com/android/ims/internal/IImsCallSession.aidl \
+	telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl \
+	telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl \
+	telephony/java/com/android/ims/internal/IImsService.aidl \
+	telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl \
+	telephony/java/com/android/ims/internal/IImsUt.aidl \
+	telephony/java/com/android/ims/internal/IImsUtListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b6a47f2..73f370d 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -203,6 +203,8 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes/android/app/maintenance)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/maintenance)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
 
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index 5e48e37..fbbae6c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15751,6 +15751,7 @@
   public final class MediaController {
     method public void addCallback(android.media.session.MediaController.Callback);
     method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
+    method public void adjustVolumeBy(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public static android.media.session.MediaController fromToken(android.media.session.MediaSessionToken);
     method public android.media.MediaMetadata getMetadata();
@@ -15760,6 +15761,7 @@
     method public android.media.session.MediaController.VolumeInfo getVolumeInfo();
     method public void removeCallback(android.media.session.MediaController.Callback);
     method public void sendControlCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+    method public void setVolumeTo(int, int);
   }
 
   public static abstract class MediaController.Callback {
@@ -15767,6 +15769,7 @@
     method public void onMetadataChanged(android.media.MediaMetadata);
     method public void onPlaybackStateChanged(android.media.session.PlaybackState);
     method public void onSessionEvent(java.lang.String, android.os.Bundle);
+    method public void onVolumeInfoChanged(android.media.session.MediaController.VolumeInfo);
   }
 
   public final class MediaController.TransportControls {
@@ -15809,8 +15812,8 @@
     method public void setPlaybackToRemote(android.media.VolumeProvider);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
-    field public static final int VOLUME_TYPE_LOCAL = 1; // 0x1
-    field public static final int VOLUME_TYPE_REMOTE = 2; // 0x2
+    field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+    field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
   }
 
   public static abstract class MediaSession.Callback {
@@ -27601,6 +27604,7 @@
   public final class CallServiceAdapter implements android.os.IBinder.DeathRecipient {
     method public void addConferenceCall(java.lang.String);
     method public void binderDied();
+    method public void cancelOutgoingCall(java.lang.String);
     method public void handleFailedOutgoingCall(android.telecomm.ConnectionRequest, int, java.lang.String);
     method public void handleSuccessfulOutgoingCall(java.lang.String);
     method public void handoffCall(java.lang.String);
@@ -27747,7 +27751,7 @@
     method public final void abort(java.lang.String);
     method public final void answer(java.lang.String);
     method public final void call(android.telecomm.CallInfo);
-    method public void createRemoteOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.SimpleResponse<android.telecomm.ConnectionRequest, android.telecomm.RemoteConnection>);
+    method public void createRemoteOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.OutgoingCallResponse<android.telecomm.RemoteConnection>);
     method public final void disconnect(java.lang.String);
     method public java.util.Collection<android.telecomm.Connection> getAllConnections();
     method public final void hold(java.lang.String);
@@ -27757,7 +27761,7 @@
     method public void onConnectionAdded(android.telecomm.Connection);
     method public void onConnectionRemoved(android.telecomm.Connection);
     method public void onCreateConferenceConnection(java.lang.String, android.telecomm.Connection, android.telecomm.Response<java.lang.String, android.telecomm.Connection>);
-    method public void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
+    method public void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.OutgoingCallResponse<android.telecomm.Connection>);
     method public void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
     method public final void onPostDialContinue(java.lang.String, boolean);
     method public final void onPostDialWait(android.telecomm.Connection, java.lang.String);
@@ -27768,6 +27772,12 @@
     method public final void unhold(java.lang.String);
   }
 
+  public static abstract interface ConnectionService.OutgoingCallResponse {
+    method public abstract void onCancel(android.telecomm.ConnectionRequest);
+    method public abstract void onFailure(android.telecomm.ConnectionRequest, int, java.lang.String);
+    method public abstract void onSuccess(android.telecomm.ConnectionRequest, CONNECTION);
+  }
+
   public class GatewayInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.net.Uri getGatewayHandle();
@@ -27848,7 +27858,7 @@
 
   public class RemoteConnectionService implements android.os.IBinder.DeathRecipient {
     method public void binderDied();
-    method public void createOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.SimpleResponse<android.telecomm.ConnectionRequest, android.telecomm.RemoteConnection>);
+    method public void createOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.OutgoingCallResponse<android.telecomm.RemoteConnection>);
     method public java.util.List<android.telecomm.Subscription> lookupSubscriptions(android.net.Uri);
   }
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 788ac56..88746bf4 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -652,6 +652,12 @@
         public int userId;
 
         /**
+         * The last time this task was active.
+         * @hide
+         */
+        public long lastActiveTime;
+
+        /**
          * The recent activity values for the highest activity in the stack to have set the values.
          * {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
          *
@@ -688,6 +694,7 @@
             }
             dest.writeInt(stackId);
             dest.writeInt(userId);
+            dest.writeLong(lastActiveTime);
         }
 
         public void readFromParcel(Parcel source) {
@@ -700,6 +707,7 @@
                     TaskDescription.CREATOR.createFromParcel(source) : null;
             stackId = source.readInt();
             userId = source.readInt();
+            lastActiveTime = source.readLong();
         }
 
         public static final Creator<RecentTaskInfo> CREATOR
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 13b922c..cb48e58 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -621,10 +621,15 @@
     }
 
     @Override
-    public ProviderInfo resolveContentProvider(String name,
-                                               int flags) {
+    public ProviderInfo resolveContentProvider(String name, int flags) {
+        return resolveContentProviderAsUser(name, flags, mContext.getUserId());
+    }
+
+    /** @hide **/
+    @Override
+    public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) {
         try {
-            return mPM.resolveContentProvider(name, flags, mContext.getUserId());
+            return mPM.resolveContentProvider(name, flags, userId);
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index ad4ccbb..6fbf87d 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -26,6 +26,7 @@
 interface ITrustManager {
     void reportUnlockAttempt(boolean successful, int userId);
     void reportEnabledTrustAgentsChanged(int userId);
+    void reportRequireCredentialEntry(int userId);
     void registerTrustListener(in ITrustListener trustListener);
     void unregisterTrustListener(in ITrustListener trustListener);
 }
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index e31c624..6e90590 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -71,6 +71,21 @@
     }
 
     /**
+     * Reports that trust is disabled until credentials have been entered for user {@param userId}.
+     *
+     * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+     *
+     * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
+     */
+    public void reportRequireCredentialEntry(int userId) {
+        try {
+            mService.reportRequireCredentialEntry(userId);
+        } catch (RemoteException e) {
+            onError(e);
+        }
+    }
+
+    /**
      * Registers a listener for trust events.
      *
      * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index c9df9c0..7b5bfbd 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -267,7 +267,7 @@
                 if (service == null) return;
 
                 BluetoothGattCharacteristic characteristic = service.getCharacteristic(
-                    charUuid.getUuid());
+                    charUuid.getUuid(), charInstId);
                 if (characteristic == null) return;
 
                 characteristic.addDescriptor(new BluetoothGattDescriptor(
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 392bfbc..be70411 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1751,6 +1751,15 @@
      * @param extras any extras to pass to the SyncAdapter.
      */
     public static void requestSync(Account account, String authority, Bundle extras) {
+        requestSyncAsUser(account, authority, UserHandle.getCallingUserId(), extras);
+    }
+
+    /**
+     * @see #requestSync(Account, String, Bundle)
+     * @hide
+     */
+    public static void requestSyncAsUser(Account account, String authority, int userId,
+            Bundle extras) {
         if (extras == null) {
             throw new IllegalArgumentException("Must specify extras.");
         }
@@ -1760,7 +1769,11 @@
                 .setExtras(extras)
                 .syncOnce()     // Immediate sync.
                 .build();
-        requestSync(request);
+        try {
+            getContentService().syncAsUser(request, userId);
+        } catch(RemoteException e) {
+            // Shouldn't happen.
+        }
     }
 
     /**
@@ -1839,6 +1852,17 @@
     }
 
     /**
+     * @see #cancelSync(Account, String)
+     * @hide
+     */
+    public static void cancelSyncAsUser(Account account, String authority, int userId) {
+        try {
+            getContentService().cancelSyncAsUser(account, authority, null, userId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Get information about the SyncAdapters that are known to the system.
      * @return an array of SyncAdapters that have registered with the system
      */
@@ -1851,6 +1875,18 @@
     }
 
     /**
+     * @see #getSyncAdapterTypes()
+     * @hide
+     */
+    public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) {
+        try {
+            return getContentService().getSyncAdapterTypesAsUser(userId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
      * Check if the provider should be synced when a network tickle is received
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
@@ -1868,6 +1904,19 @@
     }
 
     /**
+     * @see #getSyncAutomatically(Account, String)
+     * @hide
+     */
+    public static boolean getSyncAutomaticallyAsUser(Account account, String authority,
+            int userId) {
+        try {
+            return getContentService().getSyncAutomaticallyAsUser(account, authority, userId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
      * Set whether or not the provider is synced when it receives a network tickle.
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
@@ -2032,6 +2081,18 @@
     }
 
     /**
+     * @see #getIsSyncable(Account, String)
+     * @hide
+     */
+    public static int getIsSyncableAsUser(Account account, String authority, int userId) {
+        try {
+            return getContentService().getIsSyncableAsUser(account, authority, userId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
      * Set whether this account/provider is syncable.
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
@@ -2063,6 +2124,18 @@
     }
 
     /**
+     * @see #getMasterSyncAutomatically()
+     * @hide
+     */
+    public static boolean getMasterSyncAutomaticallyAsUser(int userId) {
+        try {
+            return getContentService().getMasterSyncAutomaticallyAsUser(userId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
      * Sets the master auto-sync setting that applies to all the providers and accounts.
      * If this is false then the per-provider auto-sync setting is ignored.
      * <p>This method requires the caller to hold the permission
@@ -2147,6 +2220,18 @@
     }
 
     /**
+     * @see #getCurrentSyncs()
+     * @hide
+     */
+    public static List<SyncInfo> getCurrentSyncsAsUser(int userId) {
+        try {
+            return getContentService().getCurrentSyncsAsUser(userId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
      * Returns the status that matches the authority.
      * @param account the account whose setting we are querying
      * @param authority the provider whose behavior is being queried
@@ -2162,6 +2247,19 @@
     }
 
     /**
+     * @see #getSyncStatus(Account, String)
+     * @hide
+     */
+    public static SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
+            int userId) {
+        try {
+            return getContentService().getSyncStatusAsUser(account, authority, null, userId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
      * Return true if the pending status is true of any matching authorities.
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#READ_SYNC_STATS}.
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 373f2fb..1e96713 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -60,7 +60,9 @@
      * Start a sync given a request.
      */
     void sync(in SyncRequest request);
+    void syncAsUser(in SyncRequest request, int userId);
     void cancelSync(in Account account, String authority, in ComponentName cname);
+    void cancelSyncAsUser(in Account account, String authority, in ComponentName cname, int userId);
 
     /** Cancel a sync, providing information about the sync to be cancelled. */
      void cancelRequest(in SyncRequest request);
@@ -71,6 +73,7 @@
      * @return true if the provider should be synced when a network tickle is received
      */
     boolean getSyncAutomatically(in Account account, String providerName);
+    boolean getSyncAutomaticallyAsUser(in Account account, String providerName, int userId);
 
     /**
      * Set whether or not the provider is synced when it receives a network tickle.
@@ -114,6 +117,7 @@
      * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
      */
     int getIsSyncable(in Account account, String providerName);
+    int getIsSyncableAsUser(in Account account, String providerName, int userId);
 
     /**
      * Set whether this account/provider is syncable.
@@ -124,14 +128,17 @@
     void setMasterSyncAutomatically(boolean flag);
 
     boolean getMasterSyncAutomatically();
+    boolean getMasterSyncAutomaticallyAsUser(int userId);
 
     List<SyncInfo> getCurrentSyncs();
+    List<SyncInfo> getCurrentSyncsAsUser(int userId);
 
     /**
      * Returns the types of the SyncAdapters that are registered with the system.
      * @return Returns the types of the SyncAdapters that are registered with the system.
      */
     SyncAdapterType[] getSyncAdapterTypes();
+    SyncAdapterType[] getSyncAdapterTypesAsUser(int userId);
 
     /**
      * Returns true if there is currently a operation for the given account/authority or service
@@ -152,6 +159,8 @@
      * non-null.
      */
     SyncStatusInfo getSyncStatus(in Account account, String authority, in ComponentName cname);
+    SyncStatusInfo getSyncStatusAsUser(in Account account, String authority, in ComponentName cname,
+            int userId);
 
     /**
      * Return true if the pending status is true of any matching authorities.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 720315d..9ac433f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2478,6 +2478,19 @@
             int flags);
 
     /**
+     * Find a single content provider by its base path name.
+     *
+     * @param name The name of the provider to find.
+     * @param flags Additional option flags.  Currently should always be 0.
+     * @param userId The user id.
+     *
+     * @return ContentProviderInfo Information about the provider, if found,
+     *         else null.
+     * @hide
+     */
+    public abstract ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId);
+
+    /**
      * Retrieve content provider information.
      *
      * <p><em>Note: unlike most other methods, an empty result set is indicated
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index e2f88eb..ef8c67b 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1354,7 +1354,11 @@
     /**
      * <p>Range of valid exposure
      * times used by {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}.</p>
+     * <p>The min value will be &lt;= 100e3 (100 us). For FULL
+     * capability devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} == FULL),
+     * max will be &gt;= 100e6 (100ms)</p>
      *
+     * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CaptureRequest#SENSOR_EXPOSURE_TIME
      */
     public static final Key<android.util.Range<Long>> SENSOR_INFO_EXPOSURE_TIME_RANGE =
@@ -1371,7 +1375,10 @@
      * <p>Refer to
      * StreamConfigurationMap#getOutputMinFrameDuration(int,Size)
      * for the minimum frame duration values.</p>
+     * <p>For FULL capability devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} == FULL),
+     * max will be &gt;= 100e6 (100ms).</p>
      *
+     * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CaptureRequest#SENSOR_FRAME_DURATION
      */
     public static final Key<Long> SENSOR_INFO_MAX_FRAME_DURATION =
@@ -1748,18 +1755,26 @@
     /**
      * <p>Generally classifies the overall set of the camera device functionality.</p>
      * <p>Camera devices will come in two flavors: LIMITED and FULL.</p>
-     * <p>A FULL device has the most support possible and will enable the
-     * widest range of use cases such as:</p>
+     * <p>A FULL device has the most support possible and will support below capabilities:</p>
      * <ul>
      * <li>30fps at maximum resolution (== sensor resolution) is preferred, more than 20fps is required.</li>
      * <li>Per frame control ({@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} <code>==</code> PER_FRAME_CONTROL)</li>
      * <li>Manual sensor control ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR)</li>
      * <li>Manual post-processing control ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_POST_PROCESSING)</li>
+     * <li>Arbitrary cropping region ({@link CameraCharacteristics#SCALER_CROPPING_TYPE android.scaler.croppingType} <code>==</code> FREEFORM)</li>
+     * <li>At least 3 processed (but not stalling) format output streams ({@link CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_PROC android.request.maxNumOutputProc} <code>&gt;=</code> 3)</li>
+     * <li>The required stream configuration defined in android.scaler.availableStreamConfigurations</li>
+     * <li>The required exposure time range defined in {@link CameraCharacteristics#SENSOR_INFO_EXPOSURE_TIME_RANGE android.sensor.info.exposureTimeRange}</li>
+     * <li>The required maxFrameDuration defined in {@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration}</li>
      * </ul>
      * <p>A LIMITED device may have some or none of the above characteristics.
      * To find out more refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}.</p>
      *
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     * @see CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_PROC
+     * @see CameraCharacteristics#SCALER_CROPPING_TYPE
+     * @see CameraCharacteristics#SENSOR_INFO_EXPOSURE_TIME_RANGE
+     * @see CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION
      * @see CameraCharacteristics#SYNC_MAX_LATENCY
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index dad1854..889b127 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -310,7 +310,9 @@
      * <li>{@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}</li>
      * </ul>
      * </li>
-     * <li>Lens shading map information<ul>
+     * <li>Manual lens shading map control<ul>
+     * <li>{@link CaptureRequest#SHADING_MODE android.shading.mode}</li>
+     * <li>{@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE android.statistics.lensShadingMapMode}</li>
      * <li>android.statistics.lensShadingMap</li>
      * <li>android.lens.info.shadingMapSize</li>
      * </ul>
@@ -323,6 +325,8 @@
      *
      * @see CaptureRequest#COLOR_CORRECTION_GAINS
      * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
+     * @see CaptureRequest#SHADING_MODE
+     * @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
      * @see CaptureRequest#TONEMAP_CURVE
      * @see CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS
      * @see CaptureRequest#TONEMAP_MODE
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index f702556..1646120 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -19,6 +19,7 @@
 import android.graphics.ImageFormat;
 import android.hardware.Camera;
 import android.hardware.Camera.CameraInfo;
+import android.hardware.Camera.Parameters;
 import android.hardware.Camera.Size;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
@@ -47,6 +48,8 @@
     private static final String TAG = "LegacyMetadataMapper";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
+    private static final long NS_PER_MS = 1000000;
+
     // from graphics.h
     private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
     private static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
@@ -54,10 +57,21 @@
     // for metadata
     private static final float LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS = 0.0f;
 
-    private static final long APPROXIMATE_CAPTURE_DELAY_MS = 200; // ms
-    private static final long APPROXIMATE_SENSOR_AREA = (1 << 23); // 8mp
-    private static final long APPROXIMATE_JPEG_ENCODE_TIME = 600; // ms
-    private static final long NS_PER_MS = 1000000;
+    private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW = 0; // no raw support
+    private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC = 3; // preview, video, cb
+    private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL = 1; // 1 jpeg only
+    private static final int REQUEST_MAX_NUM_INPUT_STREAMS_COUNT = 0; // no reprocessing
+
+    /** Assume 3 HAL1 stages: Exposure, Read-out, Post-Processing */
+    private static final int REQUEST_PIPELINE_MAX_DEPTH_HAL1 = 3;
+    /** Assume 3 shim stages: Preview input, Split output, Format conversion for output */
+    private static final int REQUEST_PIPELINE_MAX_DEPTH_OURS = 3;
+    /* TODO: Update above maxDepth values once we do more performance measurements */
+
+    // For approximating JPEG stall durations
+    private static final long APPROXIMATE_CAPTURE_DELAY_MS = 200; // 200 milliseconds
+    private static final long APPROXIMATE_SENSOR_AREA_PX = (1 << 23); // 8 megapixels
+    private static final long APPROXIMATE_JPEG_ENCODE_TIME_MS = 600; // 600 milliseconds
 
     /*
      * Development hijinks: Lie about not supporting certain capabilities
@@ -113,11 +127,11 @@
 
         CameraMetadataNative m = new CameraMetadataNative();
 
-        mapCameraInfo(m, info.info);
+        mapCharacteristicsFromInfo(m, info.info);
 
         Camera.Parameters params = Camera.getEmptyParameters();
         params.unflatten(parameters);
-        mapCameraParameters(m, params);
+        mapCharacteristicsFromParameters(m, params);
 
         if (VERBOSE) {
             Log.v(TAG, "createCharacteristics metadata:");
@@ -129,21 +143,51 @@
         return new CameraCharacteristics(m);
     }
 
-    private static void mapCameraInfo(CameraMetadataNative m, CameraInfo i) {
+    private static void mapCharacteristicsFromInfo(CameraMetadataNative m, CameraInfo i) {
         m.set(LENS_FACING, i.facing == CameraInfo.CAMERA_FACING_BACK ?
                 LENS_FACING_BACK : LENS_FACING_FRONT);
         m.set(SENSOR_ORIENTATION, i.orientation);
     }
 
-    private static void mapCameraParameters(CameraMetadataNative m, Camera.Parameters p) {
+    private static void mapCharacteristicsFromParameters(CameraMetadataNative m,
+            Camera.Parameters p) {
+        /*
+         * info.supportedHardwareLevel
+         */
         m.set(INFO_SUPPORTED_HARDWARE_LEVEL, INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED);
         mapStreamConfigs(m, p);
+        /*
+         * control.ae*
+         */
         mapControlAe(m, p);
+        /*
+         * control.awb*
+         */
         mapControlAwb(m, p);
-        mapCapabilities(m, p);
+        /*
+         * control.*
+         * - Anything that doesn't have a set of related fields
+         */
+        mapControlOther(m, p);
+        /*
+         * lens.*
+         */
         mapLens(m, p);
+        /*
+         * flash.*
+         */
         mapFlash(m, p);
+
+        /*
+         * request.*
+         */
+        mapRequest(m, p);
         // TODO: map other fields
+
+        /*
+         * sync.*
+         */
+        mapSync(m, p);
     }
 
     private static void mapStreamConfigs(CameraMetadataNative m, Camera.Parameters p) {
@@ -179,9 +223,15 @@
         List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
         appendStreamConfig(availableStreamConfigs,
                 HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes());
+        /*
+         * scaler.availableStreamConfigurations
+         */
         m.set(SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
                 availableStreamConfigs.toArray(new StreamConfiguration[0]));
 
+        /*
+         * scaler.availableMinFrameDurations
+         */
         // No frame durations available
         m.set(SCALER_AVAILABLE_MIN_FRAME_DURATIONS, new StreamConfigurationDuration[0]);
 
@@ -197,9 +247,15 @@
                 longestStallDuration = stallDuration;
             }
         }
+        /*
+         * scaler.availableStallDurations
+         */
         // Set stall durations for jpeg, other formats use default stall duration
         m.set(SCALER_AVAILABLE_STALL_DURATIONS, jpegStalls);
 
+        /*
+         * sensor.info.maxFrameDuration
+         */
         m.set(SENSOR_INFO_MAX_FRAME_DURATION, longestStallDuration);
     }
 
@@ -289,9 +345,8 @@
         }
     }
 
-    private static void mapCapabilities(CameraMetadataNative m, Camera.Parameters p) {
-        int[] capabilities = { REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE };
-        m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities);
+    private static void mapControlOther(CameraMetadataNative m, Camera.Parameters p) {
+        // TODO
     }
 
     private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
@@ -300,6 +355,9 @@
          *  but if it's not, we can't tell the minimum focus distance, so leave it null then.
          */
         if (p.getFocusMode() == Camera.Parameters.FOCUS_MODE_FIXED) {
+            /*
+             * lens.info.minimumFocusDistance
+             */
             m.set(LENS_INFO_MINIMUM_FOCUS_DISTANCE, LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS);
         }
     }
@@ -321,9 +379,51 @@
             flashAvailable = false;
         }
 
+        /*
+         * flash.info.available
+         */
         m.set(FLASH_INFO_AVAILABLE, flashAvailable);
     }
 
+    private static void mapRequest(CameraMetadataNative m, Parameters p) {
+        /*
+         * request.availableCapabilities
+         */
+        int[] capabilities = { REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE };
+        m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities);
+
+        /*
+         * request.maxNumOutputStreams
+         */
+        int[] outputStreams = {
+                /* RAW */
+                REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW,
+                /* Processed & Not-Stalling */
+                REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC,
+                /* Processed & Stalling */
+                REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL,
+        };
+        m.set(REQUEST_MAX_NUM_OUTPUT_STREAMS, outputStreams);
+
+        /*
+         * request.maxNumInputStreams
+         */
+        m.set(REQUEST_MAX_NUM_INPUT_STREAMS, REQUEST_MAX_NUM_INPUT_STREAMS_COUNT);
+
+        /*
+         * request.pipelineMaxDepth
+         */
+        m.set(REQUEST_PIPELINE_MAX_DEPTH,
+                (byte)(REQUEST_PIPELINE_MAX_DEPTH_HAL1 + REQUEST_PIPELINE_MAX_DEPTH_OURS));
+    }
+
+    private static void mapSync(CameraMetadataNative m, Parameters p) {
+        /*
+         * sync.maxLatency
+         */
+        m.set(SYNC_MAX_LATENCY, SYNC_MAX_LATENCY_UNKNOWN);
+    }
+
     private static void appendStreamConfig(
             ArrayList<StreamConfiguration> configs, int format, List<Camera.Size> sizes) {
         for (Camera.Size size : sizes) {
@@ -398,8 +498,8 @@
     private static long calculateJpegStallDuration(Camera.Size size) {
         long baseDuration = APPROXIMATE_CAPTURE_DELAY_MS * NS_PER_MS; // 200ms for capture
         long area = size.width * (long) size.height;
-        long stallPerArea = APPROXIMATE_JPEG_ENCODE_TIME * NS_PER_MS /
-                APPROXIMATE_SENSOR_AREA; // 600ms stall for 8mp
+        long stallPerArea = APPROXIMATE_JPEG_ENCODE_TIME_MS * NS_PER_MS /
+                APPROXIMATE_SENSOR_AREA_PX; // 600ms stall for 8mp
         return baseDuration + area * stallPerArea;
     }
 
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index e7184ed..8be5cf8 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -264,13 +264,32 @@
     }
 
     /**
-     * Adds the given {@link InetAddress} to the list of DNS servers.
+     * Adds the given {@link InetAddress} to the list of DNS servers, if not present.
      *
      * @param dnsServer The {@link InetAddress} to add to the list of DNS servers.
+     * @return true if the DNS server was added, false if it was already present.
      * @hide
      */
-    public void addDnsServer(InetAddress dnsServer) {
-        if (dnsServer != null) mDnses.add(dnsServer);
+    public boolean addDnsServer(InetAddress dnsServer) {
+        if (dnsServer != null && !mDnses.contains(dnsServer)) {
+            mDnses.add(dnsServer);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Replaces the DNS servers in this {@code LinkProperties} with
+     * the given {@link Collection} of {@link InetAddress} objects.
+     *
+     * @param addresses The {@link Collection} of DNS servers to set in this object.
+     * @hide
+     */
+    public void setDnsServers(Collection<InetAddress> dnsServers) {
+        mDnses.clear();
+        for (InetAddress dnsServer: dnsServers) {
+            addDnsServer(dnsServer);
+        }
     }
 
     /**
@@ -540,14 +559,14 @@
     }
 
     /**
-     * Returns true if this link has an IPv6 address.
+     * Returns true if this link has a global preferred IPv6 address.
      *
-     * @return {@code true} if there is an IPv6 address, {@code false} otherwise.
+     * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
      * @hide
      */
-    public boolean hasIPv6Address() {
+    public boolean hasGlobalIPv6Address() {
         for (LinkAddress address : mLinkAddresses) {
-          if (address.getAddress() instanceof Inet6Address) {
+          if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) {
             return true;
           }
         }
@@ -555,6 +574,80 @@
     }
 
     /**
+     * Returns true if this link has an IPv4 default route.
+     *
+     * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
+     * @hide
+     */
+    public boolean hasIPv4DefaultRoute() {
+        for (RouteInfo r : mRoutes) {
+          if (r.isIPv4Default()) {
+            return true;
+          }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this link has an IPv6 default route.
+     *
+     * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
+     * @hide
+     */
+    public boolean hasIPv6DefaultRoute() {
+        for (RouteInfo r : mRoutes) {
+          if (r.isIPv6Default()) {
+            return true;
+          }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this link has an IPv4 DNS server.
+     *
+     * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
+     * @hide
+     */
+    public boolean hasIPv4DnsServer() {
+        for (InetAddress ia : mDnses) {
+          if (ia instanceof Inet4Address) {
+            return true;
+          }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this link has an IPv6 DNS server.
+     *
+     * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
+     * @hide
+     */
+    public boolean hasIPv6DnsServer() {
+        for (InetAddress ia : mDnses) {
+          if (ia instanceof Inet6Address) {
+            return true;
+          }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this link is provisioned for global connectivity. For IPv6, this requires an
+     * IP address, default route, and DNS server. For IPv4, this requires only an IPv4 address,
+     * because WifiStateMachine accepts static configurations that only specify an address but not
+     * DNS servers or a default route.
+     *
+     * @return {@code true} if the link is provisioned, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isProvisioned() {
+        return (hasIPv4Address() ||
+                (hasGlobalIPv6Address() && hasIPv6DefaultRoute() && hasIPv6DnsServer()));
+    }
+
+    /**
      * Compares this {@code LinkProperties} interface name against the target
      *
      * @param target LinkProperties to compare.
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index b02a79d..9da3a51 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -161,6 +161,7 @@
     private boolean mFinished;
     private boolean mCanDoze;
     private boolean mDozing;
+    private boolean mWindowless;
     private DozeHardware mDozeHardware;
 
     private boolean mDebug = false;
@@ -520,6 +521,24 @@
     }
 
     /**
+     * Marks this dream as windowless.  Only available to doze dreams.
+     *
+     * @hide
+     */
+    public void setWindowless(boolean windowless) {
+        mWindowless = windowless;
+    }
+
+    /**
+     * Returns whether or not this dream is windowless.  Only available to doze dreams.
+     *
+     * @hide
+     */
+    public boolean isWindowless() {
+        return mWindowless;
+    }
+
+    /**
      * Returns true if this dream is allowed to doze.
      * <p>
      * The value returned by this method is only meaningful when the dream has started.
@@ -715,6 +734,7 @@
             WindowManagerGlobal.getInstance().closeAll(mWindowToken,
                     this.getClass().getName(), "Dream");
             mWindowToken = null;
+            mCanDoze = false;
         }
     }
 
@@ -744,47 +764,50 @@
 
         mWindowToken = windowToken;
         mCanDoze = canDoze;
-
-        mWindow = PolicyManager.makeNewWindow(this);
-        mWindow.setCallback(this);
-        mWindow.requestFeature(Window.FEATURE_NO_TITLE);
-        mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
-        mWindow.setFormat(PixelFormat.OPAQUE);
-
-        if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
-                windowToken, WindowManager.LayoutParams.TYPE_DREAM));
-
-        WindowManager.LayoutParams lp = mWindow.getAttributes();
-        lp.type = WindowManager.LayoutParams.TYPE_DREAM;
-        lp.token = windowToken;
-        lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
-        lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
-                    | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
-                    | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
-                    | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
-                    | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
-                    );
-        mWindow.setAttributes(lp);
-        mWindow.setWindowManager(null, windowToken, "dream", true);
-
-        applySystemUiVisibilityFlags(
-                (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
-                View.SYSTEM_UI_FLAG_LOW_PROFILE);
-
-        try {
-            getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
-        } catch (WindowManager.BadTokenException ex) {
-            // This can happen because the dream manager service will remove the token
-            // immediately without necessarily waiting for the dream to start.
-            // We should receive a finish message soon.
-            Slog.i(TAG, "attach() called after window token already removed, dream will "
-                    + "finish soon");
-            mWindow = null;
-            return;
+        if (mWindowless && !mCanDoze) {
+            throw new IllegalStateException("Only doze dreams can be windowless");
         }
+        if (!mWindowless) {
+            mWindow = PolicyManager.makeNewWindow(this);
+            mWindow.setCallback(this);
+            mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+            mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
+            mWindow.setFormat(PixelFormat.OPAQUE);
 
+            if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
+                    windowToken, WindowManager.LayoutParams.TYPE_DREAM));
+
+            WindowManager.LayoutParams lp = mWindow.getAttributes();
+            lp.type = WindowManager.LayoutParams.TYPE_DREAM;
+            lp.token = windowToken;
+            lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
+            lp.flags |= ( WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+                        | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+                        | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0)
+                        | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
+                        );
+            mWindow.setAttributes(lp);
+            mWindow.setWindowManager(null, windowToken, "dream", true);
+
+            applySystemUiVisibilityFlags(
+                    (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
+                    View.SYSTEM_UI_FLAG_LOW_PROFILE);
+
+            try {
+                getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+            } catch (WindowManager.BadTokenException ex) {
+                // This can happen because the dream manager service will remove the token
+                // immediately without necessarily waiting for the dream to start.
+                // We should receive a finish message soon.
+                Slog.i(TAG, "attach() called after window token already removed, dream will "
+                        + "finish soon");
+                mWindow = null;
+                return;
+            }
+        }
         // We need to defer calling onDreamingStarted until after onWindowAttached,
         // which is posted to the handler by addView, so we post onDreamingStarted
         // to the handler also.  Need to watch out here in case detach occurs before
@@ -792,7 +815,7 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                if (mWindow != null) {
+                if (mWindow != null || mWindowless) {
                     if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
                     mStarted = true;
                     onDreamingStarted();
@@ -878,6 +901,7 @@
                 if (isLowProfile()) pw.print(" lowprofile");
                 if (isFullscreen()) pw.print(" fullscreen");
                 if (isScreenBright()) pw.print(" bright");
+                if (isWindowless()) pw.print(" windowless");
                 if (isDozing()) pw.print(" dozing");
                 pw.println();
             }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d31c5cc..5bd6f52 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1460,4 +1460,11 @@
         }
         return activeTrustAgents;
     }
+
+    /**
+     * @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
+     */
+    public void requireCredentialEntry(int userId) {
+        getTrustManager().reportRequireCredentialEntry(userId);
+    }
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 53f46eb..ca897d5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -156,16 +156,12 @@
         android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
     <protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
-    <protected-broadcast android:name="android.btopp.intent.action.BT_OPP_HANDOVER_STARTED" />
-    <protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
     <protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
-    <protected-broadcast android:name="android.btopp.intent.action.BT_OPP_TRANSFER_PROGRESS" />
     <protected-broadcast android:name="android.btopp.intent.action.LIST" />
     <protected-broadcast android:name="android.btopp.intent.action.OPEN_OUTBOUND" />
     <protected-broadcast android:name="android.btopp.intent.action.HIDE_COMPLETE" />
     <protected-broadcast android:name="android.btopp.intent.action.CONFIRM" />
     <protected-broadcast android:name="android.btopp.intent.action.HIDE" />
-    <protected-broadcast android:name="android.btopp.intent.action.BT_OPP_TRANSFER_DONE" />
     <protected-broadcast android:name="android.btopp.intent.action.RETRY" />
     <protected-broadcast android:name="android.btopp.intent.action.OPEN" />
     <protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
@@ -284,7 +280,13 @@
     <protected-broadcast
         android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
     <!-- Defined in RestrictionsManager -->
+
     <protected-broadcast android:name="android.intent.action.REQUEST_PERMISSION" />
+    <protected-broadcast android:name="android.nfc.handover.intent.action.HANDOVER_STARTED" />
+    <protected-broadcast android:name="android.nfc.handover.intent.action.TRANSFER_DONE" />
+    <protected-broadcast android:name="android.nfc.handover.intent.action.TRANSFER_PROGRESS" />
+    <protected-broadcast android:name="android.nfc.handover.intent.action.TRANSFER_DONE" />
+
 
     <!-- ====================================== -->
     <!-- Permissions for things that cost money -->
@@ -877,6 +879,14 @@
 	android:permissionGroup="android.permission-group.NETWORK"
 	android:protectionLevel="signature|system" />
 
+    <!-- Allows sending and receiving handover transfer status from Wifi and Bluetooth
+         @hide
+    -->
+    <permission android:name="android.permission.NFC_HANDOVER_STATUS"
+                android:label="@string/permlab_handoverStatus"
+                android:description="@string/permdesc_handoverStatus"
+                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 d350ef2..708fe67 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -116,8 +116,10 @@
          specified for -large and -xlarge configurations. -->
     <dimen name="config_prefDialogWidth">320dp</dimen>
 
-    <!-- Enables or disables fading edges when marquee is enabled in TextView. -->
-    <bool name="config_ui_enableFadingMarquee">true</bool>
+    <!-- Enables or disables fading edges when marquee is enabled in TextView.
+         Off by default, since the framebuffer readback used to implement the
+         fading edges is prohibitively expensive on most GPUs. -->
+    <bool name="config_ui_enableFadingMarquee">false</bool>
 
     <!-- Whether dialogs should close automatically when the user touches outside
          of them.  This should not normally be modified. -->
@@ -1184,7 +1186,7 @@
     <bool name="config_dreamsActivatedOnDockByDefault">true</bool>
     <!-- If supported and enabled, are dreams activated when asleep and charging? (by default) -->
     <bool name="config_dreamsActivatedOnSleepByDefault">false</bool>
-    <!-- ComponentName of the default dream (Settings.Secure.SCREENSAVER_COMPONENT) -->
+    <!-- ComponentName of the default dream (Settings.Secure.DEFAULT_SCREENSAVER_COMPONENT) -->
     <string name="config_dreamsDefaultComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
 
     <!-- Are we allowed to dream while not plugged in? -->
@@ -1205,8 +1207,7 @@
          try to start this dream if possible.  The dream should typically call startDozing()
          to put the display into a low power state and allow the application processor
          to be suspended.  When the dream ends, the system will go to sleep as usual.
-         Specify the component name (Settings.Secure.SCREENSAVER_COMPONENT) or an
-         empty string if none.
+         Specify the component name or an empty string if none.
 
          Note that doze dreams are not subject to the same start conditions as ordinary dreams.
          Doze dreams will run whenever the power manager is in a dozing state. -->
@@ -1570,6 +1571,7 @@
          -->
     <string-array translatable="false" name="config_globalActionsList">
         <item>power</item>
+        <item>lockdown</item>
         <item>bugreport</item>
         <item>users</item>
     </string-array>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3da6669..6e92b07 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -443,6 +443,9 @@
     <!-- label for item that launches settings in phone options dialog [CHAR LIMIT=15]-->
     <string name="global_action_settings">Settings</string>
 
+    <!-- label for item that locks the phone and enforces that it can't be unlocked without entering a credential. [CHAR LIMIT=15] -->
+    <string name="global_action_lockdown">Lock now</string>
+
     <!-- Text to use when the number in a notification info is too large
          (greater than status_bar_notification_info_maxnum, defined in
          values/config.xml) and must be truncated. May need to be localized
@@ -2137,6 +2140,9 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_accessDrmCertificates">Allows an application to provision and use DRM certficates. Should never be needed for normal apps.</string>
 
+    <string name="permlab_handoverStatus">Receive handover transfer broadcasts.</string>
+    <string name="permdesc_handoverStatus">Allows receiving handover transfer status information.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3e82d08..7442459 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1425,6 +1425,7 @@
   <java-symbol type="string" name="global_action_silent_mode_off_status" />
   <java-symbol type="string" name="global_action_silent_mode_on_status" />
   <java-symbol type="string" name="global_action_toggle_silent_mode" />
+  <java-symbol type="string" name="global_action_lockdown" />
   <java-symbol type="string" name="invalidPuk" />
   <java-symbol type="string" name="lockscreen_carrier_default" />
   <java-symbol type="style" name="Animation.LockScreen" />
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index 9646510..4015b3d 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -38,6 +38,7 @@
 
     private static LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
     private static LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
+    private static LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
 
     public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) {
         // Check implementation of equals(), element by element.
@@ -357,7 +358,7 @@
 
         // No addresses.
         assertFalse(lp.hasIPv4Address());
-        assertFalse(lp.hasIPv6Address());
+        assertFalse(lp.hasGlobalIPv6Address());
 
         // Addresses on stacked links don't count.
         LinkProperties stacked = new LinkProperties();
@@ -366,12 +367,12 @@
         stacked.addLinkAddress(LINKADDRV4);
         stacked.addLinkAddress(LINKADDRV6);
         assertTrue(stacked.hasIPv4Address());
-        assertTrue(stacked.hasIPv6Address());
+        assertTrue(stacked.hasGlobalIPv6Address());
         assertFalse(lp.hasIPv4Address());
-        assertFalse(lp.hasIPv6Address());
+        assertFalse(lp.hasGlobalIPv6Address());
         lp.removeStackedLink(stacked);
         assertFalse(lp.hasIPv4Address());
-        assertFalse(lp.hasIPv6Address());
+        assertFalse(lp.hasGlobalIPv6Address());
 
         // Addresses on the base link.
         // Check the return values of hasIPvXAddress and ensure the add/remove methods return true
@@ -380,19 +381,29 @@
         assertTrue(lp.addLinkAddress(LINKADDRV6));
         assertEquals(1, lp.getLinkAddresses().size());
         assertFalse(lp.hasIPv4Address());
-        assertTrue(lp.hasIPv6Address());
+        assertTrue(lp.hasGlobalIPv6Address());
 
         assertTrue(lp.removeLinkAddress(LINKADDRV6));
         assertEquals(0, lp.getLinkAddresses().size());
-        assertTrue(lp.addLinkAddress(LINKADDRV4));
-        assertEquals(1, lp.getLinkAddresses().size());
-        assertTrue(lp.hasIPv4Address());
-        assertFalse(lp.hasIPv6Address());
 
-        assertTrue(lp.addLinkAddress(LINKADDRV6));
+        assertTrue(lp.addLinkAddress(LINKADDRV6LINKLOCAL));
+        assertEquals(1, lp.getLinkAddresses().size());
+        assertFalse(lp.hasGlobalIPv6Address());
+
+        assertTrue(lp.addLinkAddress(LINKADDRV4));
         assertEquals(2, lp.getLinkAddresses().size());
         assertTrue(lp.hasIPv4Address());
-        assertTrue(lp.hasIPv6Address());
+        assertFalse(lp.hasGlobalIPv6Address());
+
+        assertTrue(lp.addLinkAddress(LINKADDRV6));
+        assertEquals(3, lp.getLinkAddresses().size());
+        assertTrue(lp.hasIPv4Address());
+        assertTrue(lp.hasGlobalIPv6Address());
+
+        assertTrue(lp.removeLinkAddress(LINKADDRV6LINKLOCAL));
+        assertEquals(2, lp.getLinkAddresses().size());
+        assertTrue(lp.hasIPv4Address());
+        assertTrue(lp.hasGlobalIPv6Address());
 
         // Adding an address twice has no effect.
         // Removing an address that's not present has no effect.
diff --git a/docs/html/auto/images/logos/auto/renault.png b/docs/html/auto/images/logos/auto/renault.png
index 65a4ae3..d252aa3 100644
--- a/docs/html/auto/images/logos/auto/renault.png
+++ b/docs/html/auto/images/logos/auto/renault.png
Binary files differ
diff --git a/docs/html/auto/index.jd b/docs/html/auto/index.jd
index 116f26d..63ac287 100644
--- a/docs/html/auto/index.jd
+++ b/docs/html/auto/index.jd
@@ -59,6 +59,9 @@
   padding-left:5px;
   padding-right:15px;
 }
+.cols-leftp {
+  padding-left:95px;
+}
 </style>
 
 
@@ -325,7 +328,7 @@
                 Android Auto is coming soon to new cars from these manufacturers
               </div>
           </div>
-          <div class="cols">
+          <div class="cols cols-leftp">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/abarth.png"
                    width="120" height="120" class="img-logo" />
@@ -342,12 +345,12 @@
               <img src="{@docRoot}auto/images/logos/auto/audi.png"
                    width="120" height="120" class="img-logo" />
             </div>
+          </div>
+          <div class="cols cols-leftp">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/bentley.png"
                    width="120" height="120" class="img-logo" />
             </div>
-          </div>
-          <div class="cols">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/chevrolet.png"
                    width="120" height="120" class="img-logo" />
@@ -360,6 +363,8 @@
               <img src="{@docRoot}auto/images/logos/auto/dodge.png"
                    width="120" height="120" class="img-logo" />
             </div>
+          </div>
+          <div class="cols cols-leftp">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/fiat.png"
                    width="120" height="120" class="img-logo" />
@@ -368,8 +373,6 @@
               <img src="{@docRoot}auto/images/logos/auto/ford.png"
                    width="120" height="120" class="img-logo" />
             </div>
-          </div>
-          <div class="cols">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/honda.png"
                    width="120" height="120" class="img-logo" />
@@ -378,6 +381,8 @@
               <img src="{@docRoot}auto/images/logos/auto/hyundai.png"
                    width="120" height="120" class="img-logo" />
             </div>
+          </div>
+          <div class="cols cols-leftp">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/infinity.png"
                    width="120" height="120" class="img-logo" />
@@ -390,12 +395,12 @@
               <img src="{@docRoot}auto/images/logos/auto/kia.png"
                    width="120" height="120" class="img-logo" />
             </div>
-          </div>
-          <div class="cols">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/maserati.png"
                    width="120" height="120" class="img-logo" />
             </div>
+          </div>
+          <div class="cols cols-leftp">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/mazda.png"
                    width="120" height="120" class="img-logo" />
@@ -413,7 +418,7 @@
                    width="120" height="120" class="img-logo" />
             </div>
           </div>
-          <div class="cols">
+          <div class="cols cols-leftp">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/ram.png"
                    width="120" height="120" class="img-logo" />
@@ -430,12 +435,12 @@
               <img src="{@docRoot}auto/images/logos/auto/skoda.png"
                    width="120" height="120" class="img-logo" />
             </div>
+          </div>
+          <div class="cols cols-leftp">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/subaru.png"
                    width="120" height="120" class="img-logo" />
             </div>
-          </div>
-          <div class="cols">
             <div class="col-5">
               <img src="{@docRoot}auto/images/logos/auto/suzuki.png"
                    width="120" height="120" class="img-logo" />
@@ -448,14 +453,6 @@
               <img src="{@docRoot}auto/images/logos/auto/volvo.png"
                    width="120" height="120" class="img-logo" />
             </div>
-            <div class="col-5">
-              <!--<img src="/auto/images/logos/auto/skoda.png"
-                   width="120" height="120" class="img-logo" />-->
-            </div>
-            <div class="col-5">
-              <!--<img src="/auto/images/logos/auto/skoda.png"
-                   width="120" height="120" class="img-logo" />-->
-            </div>
           </div>
         </div>
       </div>
diff --git a/docs/html/design/auto/index.jd b/docs/html/design/auto/index.jd
index aac79ab..c970cac 100644
--- a/docs/html/design/auto/index.jd
+++ b/docs/html/design/auto/index.jd
@@ -1,4 +1,4 @@
-page.title=Auto
+page.title=Android Auto
 @jd:body
 
 <style>
diff --git a/docs/html/design/devices.jd b/docs/html/design/devices.jd
index 0015d01..c67e585 100644
--- a/docs/html/design/devices.jd
+++ b/docs/html/design/devices.jd
@@ -13,8 +13,8 @@
 #text-overlay {
   position: absolute;
   left: 0;
-  top: 420px;
-  width: 360px;
+  top: 410px;
+  width: 340px;
 
 }
 #hero-image {
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
index ddeda5c..278617b 100644
--- a/docs/html/design/downloads/index.jd
+++ b/docs/html/design/downloads/index.jd
@@ -2,27 +2,12 @@
 page.tags=Icons,stencils,color swatches
 @jd:body
 
-<div class="layout-content-row">
-  <div class="layout-content-col span-9">
 
-<p>Want everything? We've bundled all the downloads available on Android Design, except for the
-  <a href="#roboto">Roboto</a> font family, into a single ZIP file. You can also download
-  individual files listed below.</p>
+<p>You may use these materials without restriction to facilitate your app design
+and implementation.</p>
 
-<p>You may use these materials without restriction in your apps and to develop your apps.</p>
 
-  </div>
-  <div class="layout-content-col span-4">
-
-<p>
-  <a class="download-button" onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'All Design Assets']);"
-    href="{@docRoot}downloads/design/Android_Design_Downloads_20131106.zip">Download All</a>
-</p>
-
-  </div>
-</div>
-
-<h2 id="stencils">Stencils and Sources</h2>
+<h2 id="stencils">Phone &amp; Tablet Stencils</h2>
 
 <div class="layout-content-row">
   <div class="layout-content-col span-5">
@@ -54,6 +39,11 @@
   </div>
 </div>
 
+
+
+
+
+
 <h2 id="action-bar-icon-pack">Action Bar Icon Pack</h2>
 
 <div class="layout-content-row">
@@ -81,6 +71,76 @@
   </div>
 </div>
 
+
+
+
+
+<h2 id="Wear">Android Wear Materials</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+  <h4>UI toolkit</h4>
+<p>The toolkit contains detailed specs and measurements of all of the primary Android Wear UI components. Available in PDF and Illustrator formats.</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/downloads_wear_toolkit.png" width="220">
+
+  </div>
+  <div class="layout-content-col span-4">
+  <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear Toolkit AI']);"
+    href="{@docRoot}downloads/design/Android_Design_Stencils_Sources_20131106.zip">Adobe&reg; Illustrator&reg; Toolkit</a>
+
+  <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear Toolkit PDF']);"
+    href="{@docRoot}downloads/design/Android_Design_Stencils_Sources_20131106.zip">PDF Toolkit</a>
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+  <h4>Sample app user flows</h4>
+<p>Examples of how to chain together simple Android Wear UI components into common user flows, from simple notifications to complex interactions involving full screen activities.
+</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/downloads_wear_flows.png" width="220">
+
+  </div>
+  <div class="layout-content-col span-4">
+  <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear Sample Flows AI']);"
+    href="{@docRoot}downloads/design/Android_Design_Stencils_Sources_20131106.zip">Adobe&reg; Illustrator&reg; App Flows</a>
+  <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear Sample Flows PDF']);"
+    href="{@docRoot}downloads/design/Android_Design_Stencils_Sources_20131106.zip">PDF App Flows</a>
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+  <h4>Sample app design mocks</h4>
+<p>Stream cards and UI elements for some example apps in fully editable PSD format.
+</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/downloads_wear_psds.png" width="220">
+
+  </div>
+  <div class="layout-content-col span-4">
+  <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Wear Sample PSD Mocks']);"
+    href="{@docRoot}downloads/design/Android_Wear_Sample_Assets.zip">Adobe&reg; Photoshop&reg; mocks</a>
+  </div>
+</div>
+
+
+
+
+
+
+
 <h2 id="style">Style</h2>
 
 <div class="layout-content-row">
@@ -89,6 +149,7 @@
 <h4 id="roboto">Roboto</h4>
 <p>Ice Cream Sandwich introduced a new type family named Roboto, created specifically for the
 requirements of UI and high-resolution screens.</p>
+<p>For Android Wear, Roboto Condensed is the system font and the Regular and Light variants should be used by all Wear apps.</p>
 <p><a href="{@docRoot}design/style/typography.html">More on Roboto</a></p>
 <p><a href="http://www.google.com/fonts/specimen/Roboto" class="external-link">Roboto on Google Fonts</a></p>
 <p><a href="http://www.google.com/fonts/specimen/Roboto+Condensed" class="external-link">Roboto Condensed on Google Fonts</a></p>
diff --git a/docs/html/design/media/android-tv.png b/docs/html/design/media/android-tv.png
new file mode 100644
index 0000000..98005cd
--- /dev/null
+++ b/docs/html/design/media/android-tv.png
Binary files differ
diff --git a/docs/html/design/media/device_family.png b/docs/html/design/media/device_family.png
index 7889884..96b31d3 100644
--- a/docs/html/design/media/device_family.png
+++ b/docs/html/design/media/device_family.png
Binary files differ
diff --git a/docs/html/design/media/downloads_wear_flows.png b/docs/html/design/media/downloads_wear_flows.png
new file mode 100644
index 0000000..5669a2d
--- /dev/null
+++ b/docs/html/design/media/downloads_wear_flows.png
Binary files differ
diff --git a/docs/html/design/media/downloads_wear_psds.png b/docs/html/design/media/downloads_wear_psds.png
new file mode 100644
index 0000000..2b071a3
--- /dev/null
+++ b/docs/html/design/media/downloads_wear_psds.png
Binary files differ
diff --git a/docs/html/design/media/downloads_wear_toolkit.png b/docs/html/design/media/downloads_wear_toolkit.png
new file mode 100644
index 0000000..c3d30e8
--- /dev/null
+++ b/docs/html/design/media/downloads_wear_toolkit.png
Binary files differ
diff --git a/docs/html/design/media/wear/2d_picker_indicated.png b/docs/html/design/media/wear/2d_picker_indicated.png
new file mode 100644
index 0000000..d31c099
--- /dev/null
+++ b/docs/html/design/media/wear/2d_picker_indicated.png
Binary files differ
diff --git a/docs/html/design/media/wear/Bluebird.png b/docs/html/design/media/wear/Bluebird.png
index 447e643..7b911c7 100644
--- a/docs/html/design/media/wear/Bluebird.png
+++ b/docs/html/design/media/wear/Bluebird.png
Binary files differ
diff --git a/docs/html/design/media/wear/Dismissing-cards.png b/docs/html/design/media/wear/Dismissing-cards.png
new file mode 100644
index 0000000..973ef39
--- /dev/null
+++ b/docs/html/design/media/wear/Dismissing-cards.png
Binary files differ
diff --git a/docs/html/design/media/wear/appstructuresample.png b/docs/html/design/media/wear/appstructuresample.png
new file mode 100644
index 0000000..0e5b86f
--- /dev/null
+++ b/docs/html/design/media/wear/appstructuresample.png
Binary files differ
diff --git a/docs/html/design/media/wear/assets_specifics.png b/docs/html/design/media/wear/assets_specifics.png
index 35a3819..00f97d1 100644
--- a/docs/html/design/media/wear/assets_specifics.png
+++ b/docs/html/design/media/wear/assets_specifics.png
Binary files differ
diff --git a/docs/html/design/media/wear/biggesture.png b/docs/html/design/media/wear/biggesture.png
new file mode 100644
index 0000000..6c6f0cd
--- /dev/null
+++ b/docs/html/design/media/wear/biggesture.png
Binary files differ
diff --git a/docs/html/design/media/wear/fitness.png b/docs/html/design/media/wear/context_fitness.png
similarity index 100%
rename from docs/html/design/media/wear/fitness.png
rename to docs/html/design/media/wear/context_fitness.png
Binary files differ
diff --git a/docs/html/design/media/wear/context_lights.png b/docs/html/design/media/wear/context_lights.png
new file mode 100644
index 0000000..6374bdd
--- /dev/null
+++ b/docs/html/design/media/wear/context_lights.png
Binary files differ
diff --git a/docs/html/design/media/wear/contextualnotification.png b/docs/html/design/media/wear/context_running.png
similarity index 87%
rename from docs/html/design/media/wear/contextualnotification.png
rename to docs/html/design/media/wear/context_running.png
index 1ec7ac8..8b44e8c 100644
--- a/docs/html/design/media/wear/contextualnotification.png
+++ b/docs/html/design/media/wear/context_running.png
Binary files differ
diff --git a/docs/html/design/media/wear/context_workout.png b/docs/html/design/media/wear/context_workout.png
new file mode 100644
index 0000000..2ed8901
--- /dev/null
+++ b/docs/html/design/media/wear/context_workout.png
Binary files differ
diff --git a/docs/html/design/media/wear/customlayout.png b/docs/html/design/media/wear/customlayout.png
new file mode 100644
index 0000000..6a3cd9a
--- /dev/null
+++ b/docs/html/design/media/wear/customlayout.png
Binary files differ
diff --git a/docs/html/design/media/wear/five_seconds.gif b/docs/html/design/media/wear/five_seconds.gif
new file mode 100644
index 0000000..199ceb9
--- /dev/null
+++ b/docs/html/design/media/wear/five_seconds.gif
Binary files differ
diff --git a/docs/html/design/media/wear/gross_gestures.png b/docs/html/design/media/wear/gross_gestures.png
new file mode 100644
index 0000000..1faad9a
--- /dev/null
+++ b/docs/html/design/media/wear/gross_gestures.png
Binary files differ
diff --git a/docs/html/design/media/wear/peek-card.png b/docs/html/design/media/wear/peek-card.png
new file mode 100644
index 0000000..916f157
--- /dev/null
+++ b/docs/html/design/media/wear/peek-card.png
Binary files differ
diff --git a/docs/html/design/media/wear/peek_card.png b/docs/html/design/media/wear/peek_card.png
deleted file mode 100644
index 2b12297..0000000
--- a/docs/html/design/media/wear/peek_card.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/media/wear/round_noframe.png b/docs/html/design/media/wear/round_noframe.png
new file mode 100644
index 0000000..7a9759b
--- /dev/null
+++ b/docs/html/design/media/wear/round_noframe.png
Binary files differ
diff --git a/docs/html/design/media/wear/separate-info-cards.png b/docs/html/design/media/wear/separate-info-cards.png
new file mode 100644
index 0000000..59ee084
--- /dev/null
+++ b/docs/html/design/media/wear/separate-info-cards.png
Binary files differ
diff --git a/docs/html/design/media/wear/vision_music.png b/docs/html/design/media/wear/vision_music.png
new file mode 100644
index 0000000..b676d20
--- /dev/null
+++ b/docs/html/design/media/wear/vision_music.png
Binary files differ
diff --git a/docs/html/design/media/wear/vision_navigation.png b/docs/html/design/media/wear/vision_navigation.png
new file mode 100644
index 0000000..ef56977
--- /dev/null
+++ b/docs/html/design/media/wear/vision_navigation.png
Binary files differ
diff --git a/docs/html/design/media/wear/vision_traffic.png b/docs/html/design/media/wear/vision_traffic.png
new file mode 100644
index 0000000..2affa22
--- /dev/null
+++ b/docs/html/design/media/wear/vision_traffic.png
Binary files differ
diff --git a/docs/html/design/media/wear/vision_voice.png b/docs/html/design/media/wear/vision_voice.png
new file mode 100644
index 0000000..25fd49e
--- /dev/null
+++ b/docs/html/design/media/wear/vision_voice.png
Binary files differ
diff --git a/docs/html/design/media/wear/wear_checkin.png b/docs/html/design/media/wear/wear_checkin.png
new file mode 100644
index 0000000..9aeb267
--- /dev/null
+++ b/docs/html/design/media/wear/wear_checkin.png
Binary files differ
diff --git a/docs/html/design/tv/index.jd b/docs/html/design/tv/index.jd
index 5534724..d144ff01 100644
--- a/docs/html/design/tv/index.jd
+++ b/docs/html/design/tv/index.jd
@@ -1,9 +1,9 @@
-page.title=TV
+page.title=Android TV
 @jd:body
 
 
-<img src="{@docRoot}preview/tv/design/images/atv-home.jpg"
-  width="460" height="283" style="float:right;margin:0 0 40px 40px" /> 
+<img src="{@docRoot}design/media/android-tv.png"
+  width="460" style="float:right;margin:0 0 40px 40px" /> 
 
 
 <p>Android TV is <strong>coming soon</strong> and lets you engage your users in a new, shared environment.</p>
diff --git a/docs/html/design/wear/creative-vision.jd b/docs/html/design/wear/creative-vision.jd
index 4530744..aee115c 100644
--- a/docs/html/design/wear/creative-vision.jd
+++ b/docs/html/design/wear/creative-vision.jd
@@ -1,34 +1,54 @@
-page.title=Creative Vision for Wear
+page.title=Creative Vision for Android Wear
 @jd:body
 
+<style>
+div.span-13 {
+  margin:10px 0;
+}
+div.span-13 img {
+  float:left;
+  margin:2px 20px 40px 0;
+}
+div.span-13 p {
+  margin-left:167px;
+}
+div.span-13 h2 {
+  margin-top:0;
+  }
+</style>
 
 <p>Android Wear devices provide just the right information at just the right time,
 allowing users to be more connected to both the virtual world and the real world. Great Android
 Wear experiences are:</p>
 
 
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-    <h4>Launched automatically</h4>
+  <div class="layout-content-col span-13">
+    <img src="{@docRoot}design/media/wear/vision_traffic.png" width="147" height="147" />
+
+    <h2 id="Launched">Launched automatically</h2>
     <p>Most people are used to launching apps by clicking an icon. Android Wear is different. Wearable apps are aware of the user’s context - time, location, physical activity, and so on. The apps use this information to insert cards into the stream when they become relevant. This makes Android Wear timely, relevant and very specific.</p>
   </div>
-  <div class="layout-content-col span-6" style="margin-left:75px">
-  <h4>Glanceable</h4>
-  <p>A classic wrist watch is designed to let you see the time in a split second and get on with what you were doing. Designing for Android Wear is no different. The less time it takes to use your software, the more time the user can be present in whatever they are doing. Android wear is fast, sharp and immediate.</p>
-  </div>
-</div>
 
+  <div class="layout-content-col span-13">
+    <img src="{@docRoot}design/media/wear/vision_navigation.png" width="147" height="147" />
 
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-  <h4>Zero or low interaction</h4>
-  <p>Staying true to the strengths afforded by a smaller form factor, Android Wear focuses on simple interactions, only requiring input by the user when absolutely necessary. Most inputs are based around touch swipes or voice, and inputs requiring fine-grained finger movements are avoided. Android Wear is gestural, simple, and fast.</p>
+    <h2 id="Glanceable">Glanceable</h2>
+    <p>A classic wrist watch is designed to let you see the time in a split second and get on with what you were doing. Designing for Android Wear is no different. The less time it takes to use your software, the more time the user can be present in whatever they are doing. Android wear is fast, sharp and immediate.</p>
   </div>
-  <div class="layout-content-col span-6" style="margin-left:75px">
-  <h4>All about suggest and demand</h4>
-  <p>Android Wear is like a great personal assistant: it knows you and your preferences, it only interrupts you when absolutely necessary, and it’s always on hand to provide a ready answer. Android Wear is helpful, respectful, and responsive.</p>
+
+  <div class="layout-content-col span-13">
+    <img src="{@docRoot}design/media/wear/vision_voice.png" width="147" height="147" style="border: 1px solid #ddd;" />
+
+    <h2 id="SuggestDemand">All about suggest and demand</h2>
+    <p>Android Wear is like a great personal assistant: it knows you and your preferences, it only interrupts you when absolutely necessary, and it’s always on hand to provide a ready answer. Android Wear is helpful, respectful, and responsive.</p>
   </div>
-</div>
+
+  <div class="layout-content-col span-13">
+    <img src="{@docRoot}design/media/wear/vision_music.png" width="147" height="147" />
+
+    <h2 id="Interaction">Zero or low interaction</h2>
+    <p>Staying true to the strengths afforded by a smaller form factor, Android Wear focuses on simple interactions, only requiring input by the user when absolutely necessary. Most inputs are based around touch swipes or voice, and inputs requiring fine-grained finger movements are avoided. Android Wear is gestural, simple, and fast.</p>
+  </div>
 
 <p>By providing a smart connection to the rest of the world while respecting the user’s attention, Android Wear feels personal and global, simple and smart, unobtrusive and ever-ready. Applications that represent these principles will feel most at home in the overall Android Wear experience.</p>
 
diff --git a/docs/html/design/wear/index.jd b/docs/html/design/wear/index.jd
index 3536445..d6202d1 100644
--- a/docs/html/design/wear/index.jd
+++ b/docs/html/design/wear/index.jd
@@ -1,9 +1,9 @@
-page.title=Wear
+page.title=Android Wear
 @jd:body
 
 
 
-<p>Designing apps for wearables powered by Android Wear
+<p>Designing apps for wearable devices powered by Android Wear
 is substantially different than designing for phones or
 tablets: different strengths and weaknesses, different use cases, different ergonomics.
 To get started, you should understand the overall vision for the Android Wear experience,
@@ -26,7 +26,9 @@
 
 <p>This UI model ensures that users don’t have to launch many different applications to check for updates; they can simply glance at their stream for a brief update on what’s important to them.</p>
 
-<p>Cards in the stream are more than simple notifications. They can be swiped horizontally to reveal additional pages. Further horizontal swiping may reveal buttons, allowing the user to take action on the notification. Cards can also be dismissed by swiping left to right, removing them from the stream until the next time the app has useful information to display.</p>
+<p>Cards in the stream are more than simple notifications. They can be swiped horizontally to reveal additional
+<a href="{@docRoot}design/wear/patterns.html#Pages">pages</a>. Further horizontal swiping may reveal
+<a href="{@docRoot}design/wear/patterns.html#Actions">buttons</a>, allowing the user to take action on the notification. Cards can also be dismissed by swiping left to right, removing them from the stream until the next time the app has useful information to display.</p>
 
 
 
diff --git a/docs/html/design/wear/patterns.jd b/docs/html/design/wear/patterns.jd
index 8f4698c..274b62f 100644
--- a/docs/html/design/wear/patterns.jd
+++ b/docs/html/design/wear/patterns.jd
@@ -1,26 +1,22 @@
-page.title=UI Patterns for Wear
+page.title=UI Patterns for Android Wear
 @jd:body
 
 
 
 <p>Android Wear is used for micro-interactions, and so adhering to consistent design patterns that users are already accustomed to is paramount.</p>
 
-<h2>Cards</h2>
+<h2 id="Cards">Cards</h2>
 
 <p>Cards in the stream can take slightly different forms:</p>
 
-<div class="framed-wear-square-small" style="float:left;margin:0 20px 20px 0">
-  <img src="{@docRoot}design/media/wear/Bluebird.png">
-</div>
+  <img src="{@docRoot}design/media/wear/Bluebird.png" width="147" height="147" style="float:left;margin:0 0 20px 0px">
 
-<div class="framed-wear-square-small" style="float:left;margin:0 20px 20px 0">
-  <img src="{@docRoot}design/media/wear/single_action_controls.jpg">
-</div>
 
-<div class="framed-wear-square-small" style="float:left;margin:0 20px 20px 0">
-  <img src="{@docRoot}design/media/wear/expandable_stacks.png">
-</div>
-                
+  <img src="{@docRoot}design/media/wear/single_action_controls.jpg" width="147" height="147" style="float:left;margin:0 0 20px 40px">
+
+
+  <img src="{@docRoot}design/media/wear/expandable_stacks.png" width="147" height="147" style="float:left;margin:0 0 20px 40px">
+
 <ul style="clear:both">
 <li>Standard cards for displaying information from a notification</li>
 <li>Single-action controls (such as a play/pause toggle)</li>
@@ -28,28 +24,27 @@
 </ul>
 
 
-<h2>App icons</h2>
+<h2 id="Icons">App icons</h2>
 
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 60px">
-  <img src="{@docRoot}design/media/wear/clear_bold_type.jpg">
-</div>
+  <img src="{@docRoot}design/media/wear/clear_bold_type.jpg" width="147" height="147" style="float:right;margin:0 0 20px 40px">
 
 <p>App icons appear in a fixed position overhanging the edge at the top right of the card by default for all notifications in the Context Stream. This is an opportunity for cards to be recognized as coming from a specific source. Photo backgrounds should be used only to convey information, not to brand a card. App icons are necessary only on the leftmost card; it is not necessary to add the app icon to pages.</p>
 
-<h2 style="clear:both">Pages</h2>
+<h2 id="Pages" style="clear:both">Pages</h2>
 
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
-  <img src="{@docRoot}design/media/wear/separate_info_cards_2.jpg">
-</div>
-
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
-  <img src="{@docRoot}design/media/wear/separate_info_cards_1.jpg">
-</div>
+  <img src="{@docRoot}design/media/wear/separate-info-cards.png" height="147" style="float:right;margin:0 0 20px 40px">
 
 <p>Supplementary information should be displayed on additional cards to the right of a main Context Stream card. In most cases one additional detail card should be sufficient. For example, a weather card might show the weather for the current location today, with subsequent days listed in an additional card to the right. Keep the number of detail cards as low as possible. Actions (see below) should always come after pages; don’t change the order or interleave them.</p>
 
 
-<h2 style="clear:both">Dismissing cards</h2>
+<a class="notice-developers left" href="{@docRoot}training/wearables/notifications/pages.html">
+  <div>
+    <h3>Developer Docs</h3>
+    <p>Adding Pages to a Notification</p>
+  </div>
+</a>
+
+<h2 id="Dismissing" style="clear:both">Dismissing cards</h2>
 
   <img src="{@docRoot}design/media/wear/dismiss_cards.png" height="147">
 
@@ -57,24 +52,20 @@
 
 
 
-<h2 style="clear:both">Action buttons</h2>
+<h2 id="Actions" style="clear:both">Action buttons</h2>
 
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
-  <img src="{@docRoot}design/media/wear/action_button.png">
-</div>
+  <img src="{@docRoot}design/media/wear/action_button.png" width="147" height="147" style="float:right;margin:0 0 20px 40px">
 
 <p>Where the user may need to take action on the information shown in a notification, you can provide action buttons. These are system-rendered buttons that appear to the right of detail cards. They consist of a white icon set on a blue system-rendered circular button and a short caption with a verb. Actions should be limited to three for a single card row.</p>
 
-<p>Tapping on an action button can cause an action to be executed; or an action to be continued on the companion handheld; or a full screen activity to be invoked for further input (see “2D Picker” section below).</p>
+<p>Tapping on an action button can cause an action to be executed; or an action to be continued on the companion handheld; or a full screen activity to be invoked for further input (see the <a href="#2DPicker">2D Picker</a> section below).</p>
 
-<p>Refer to the UI Toolkit provided in the Downloads section for detailed specs regarding action icons.</p>
+<p>Refer to the UI Toolkit provided in the <a href="{@docRoot}design/downloads/index.html#Wear">Downloads</a> page for detailed specs regarding action icons.</p>
 
 
-<h2 style="clear:both">Action countdown and confirmation</h2>
+<h2 id="Countdown" style="clear:both">Action countdown and confirmation</h2>
 
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
-  <img src="{@docRoot}design/media/wear/countdown.png">
-</div>
+  <img src="{@docRoot}design/media/wear/countdown.png" width="149" height="149" style="float:right;margin:0 0 20px 40px">
 
 <p>Where tapping on an action button results in an action being executed, one of the following can happen:</p>
 
@@ -86,20 +77,16 @@
 </ol>
 
 
-<h2 style="clear:both">Continuing activities on phone</h2>
+<h2 id="Continuing" style="clear:both">Continuing activities on phone</h2>
 
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
-  <img src="{@docRoot}design/media/wear/continue_phone.png">
-</div>
+  <img src="{@docRoot}design/media/wear/continue_phone.png" width="147" height="147" style="float:right;margin:0 0 20px 40px">
 
 <p>Developers should attempt to perform actions on the wearable device wherever possible. In cases where the phone must be used, a generic animation should be played once the action button has been tapped and the corresponding Android app will open on the phone.</p>
 
 
-<h2 style="clear:both">Actions on cards (such as media controls)</h2>
+<h2 id="ActionOnCard" style="clear:both">Actions on cards (such as media controls)</h2>
 
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
-  <img src="{@docRoot}design/media/wear/action_on_card.png">
-</div>
+  <img src="{@docRoot}design/media/wear/action_on_card.png" width="147" height="147" style="float:right;margin:0 0 20px 40px">
 
 <p>Some cards may benefit from having tappable actions directly on a card. Some guidance on when to use this pattern versus using an action button:</p>
 
@@ -113,14 +100,20 @@
 <p>Good examples of using an action on card include: play / pause music; toggle light switch on and off; navigate to an address; call a phone number.</p>
 
 
-<h2 style="clear:both">Card stacks</h2>
-<img src="/wear/images/11_bundles_B.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" alt="">
-<img src="/wear/images/11_bundles_A.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" alt="">
+<h2 id="Stacks" style="clear:both">Card stacks</h2>
+  <img src="{@docRoot}design/media/wear/expandable_stacks.png" width="147" height="147" style="float:right;margin:0 0 20px 40px">
 <p>Card stacks group related cards together and allow them to be progressively expanded vertically in the stream. A tap on a stack fans the cards out so that the top edge of each card can be seen. A subsequent tap on a fanned card reveals that card fully. Stacks of cards revert to a fully collapsed state once the user has swiped away from them.</p>
 
 
+<a class="notice-developers left" style="clear:none" href="{@docRoot}training/wearables/notifications/stacks.html">
+  <div>
+    <h3>Developer Docs</h3>
+    <p>Stacking Notifications</p>
+  </div>
+</a>
 
-<h2 style="clear:both">2D Picker</h2>
+
+<h2 id="2DPicker" style="clear:both">2D Picker</h2>
 
 <p>A 2D Picker component in your app can be invoked from the cue card or from an action button. It allows users to choose from a list of items, and optionally select an attribute of each item. For example, in response to a voice action to “buy tickets to a movie tonight,” you could show a 2D Picker with a vertical list of movies playing, with each movie having a horizontal list of showtimes.</p>
 
@@ -128,23 +121,29 @@
 
 <p>In some instances, further information may be required. In these cases, the most probable default values for these choices should be chosen on the user’s behalf with the option to edit before completing the action. This pattern is in keeping with Android Wear’s core design principle of minimizing interactions required.</p>
 
+<p>More information about how to use the 2D Picker pattern is provided in the <a href="{@docRoot}design/wear/structure.html#2DPicker">App Structure</a> guide.</p>
 
-<h2 style="clear:both">Voice commands</h2>
 
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
-  <img src="{@docRoot}design/media/wear/voice_commands.png">
-</div>
+<h2 id="Voice" style="clear:both">Voice commands</h2>
+
+  <img src="{@docRoot}design/media/wear/voice_commands.png" width="147" height="147" style="float:right;margin:0 0 20px 40px">
 
 <p>It is possible for apps to take action in response to Android voice commands that invoke intents. For example, an app can register for the “Take a note” intent and capture the subsequent voice input for processing. In the case where multiple apps registered for the same intent, user preference will be captured once and saved. Users can edit their intent preferences in the Android Wear app on their handheld.</p>
 
-
-<h2 style="clear:both">Selection List</h2>
-
-<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
-  <img src="{@docRoot}design/media/wear/selection_list.png">
-</div>
-
-<p>Choosing an item from a list is a common interaction. The Selection List pattern (available as the WearableListView component) creates a simple list optimized for ease of use on a small screen: the focused item snaps to the center of the screen, and a single tap selects. This widget is recommended as a common pattern for selecting items. It is used throughout the system UI, including in the list that can be accessed by swiping up on the cue card.</p>
+<a class="notice-developers left" style="clear:none" href="{@docRoot}training/wearables/apps/voice.html">
+  <div>
+    <h3>Developer Docs</h3>
+    <p>Adding Voice Capabilities</p>
+  </div>
+</a>
 
 
-<p>Of course, it is possible for Android Wear apps to extend themselves beyond the familiarities of these patterns. For a deeper look at the options available, see the section on App Structure.</p>
+<h2 id="Selection" style="clear:both">Selection List</h2>
+
+  <img src="{@docRoot}design/media/wear/selection_list.png" width="147" height="147" style="float:right;margin:0 0 20px 40px;border:1px solid #ddd">
+
+<p>Choosing an item from a list is a common interaction. The Selection List pattern (available as the <a
+href="{@docRoot}training/wearables/apps/layouts.html#UiLibrary"><code>WearableListView</code></a> component) creates a simple list optimized for ease of use on a small screen: the focused item snaps to the center of the screen, and a single tap selects. This widget is recommended as a common pattern for selecting items. It is used throughout the system UI, including in the list that can be accessed by swiping up on the cue card.</p>
+
+
+<p>Of course, it is possible for Android Wear apps to extend themselves beyond the familiarities of these patterns. For a deeper look at the options available, see the <a href="{@docRoot}design/wear/structure.html">App Structure</a> guide.</p>
diff --git a/docs/html/design/wear/principles.jd b/docs/html/design/wear/principles.jd
index a214435..6286a92 100644
--- a/docs/html/design/wear/principles.jd
+++ b/docs/html/design/wear/principles.jd
@@ -1,10 +1,18 @@
-page.title=Design Principles for Wear
+page.title=Design Principles for Android Wear
 @jd:body
 
 <style>
 p.try {
-  background:#e4e4e4;
-  padding:10px;
+  color:#888;
+}
+p.try b {
+font-size: 22px;
+font-weight: 200;
+padding: 0 0 5px;
+display: block;
+}
+h2 {
+  margin-top:50px;
 }
 </style>
 
@@ -13,40 +21,55 @@
 
 
 <h2>Focus on not stopping the user and all else will follow</h2>
+
+<img src="{@docRoot}design/media/wear/five_seconds.gif" height="147" style="float:right;margin:10px 0 0 40px" />
+<p class="img-caption" style="width:315px;float:right;clear:right;margin:5px 0 30px 40px">
+The time required for each action on the left is 5 seconds.</p>
+
 <p>A watch is a perfect form factor for a device that you can use while doing something else, such as cooking, eating, walking, running, or even having a conversation. If using your wearable app causes the user to stop whatever they’re doing, it’s a good occasion to consider how to improve it using the principles in this section.</p>
 
-<p class="try"><strong>Try this:</strong> Time a typical use of your Wear app. If using it takes more than 5 seconds, you should think about making your app more focused. Also try using your app while you’re having a conversation, and see how it affects your train of thought and eye contact.</p>
+<p class="try" ><b>Try this:</b> Time a typical use of your Wear app. If using it takes more than 5 seconds, you should think about making your app more focused. Also try using your app while you’re having a conversation, and see how it affects your train of thought and eye contact.</p>
 
 
-<h2>Design for big gestures</h2>
+<h2 id="BigGestures">Design for big gestures</h2>
+
+<img src="{@docRoot}design/media/wear/biggesture.png" alt="" height="147" style="float:right;margin:10px 0 0 40px" />
+<p class="img-caption" style="width:315px;float:right;clear:right;margin:5px 0 30px 40px">
+Use few and large touch targets.</p>
 
 <p>When you swipe through photos on your phone you’re using a large area of the display, and you don’t have to be precise at all. That’s the best kind of interaction for a wearable device. Your users are going to use your app in all sorts of situations, the least frequent one might actually be sitting down at their desk.</p>
 
-<p class="try"><strong>Try this:</strong> Use your app in various everyday situations, such as walking, eating, talking to people, or ordering coffee. If you have to slow down while walking or stop the conversation to be precise, you should consider how your gestures could be bigger.</p>
+<p class="try"><b>Try this:</b> Use your app in various everyday situations, such as walking, eating, talking to people, or ordering coffee. If you have to slow down while walking or stop the conversation to be precise, you should consider how your gestures could be bigger.</p>
 
-<h2>Think about stream cards first</h2>
+
+<h2 id="CardsFirst">Think about stream cards first</h2>
+
+<p class="img-caption" style="width:150px;float:right;clear:right;margin:10px 0 30px 25px">An app that offers to check in users could appear in the stream suggesting the most likely place nearby, after a certain amount of time.</p>
+
+<img src="{@docRoot}design/media/wear/wear_checkin.png" style="float:right;margin:10px 0 40px 40px" width="147" height="147">
+
 <p>The best experience on a wearable device is when the right content is there just when the user needs it. You can figure out when to show your cards with sensors, or events happening in the cloud. For the cases where it’s impossible to know when the user needs your app, you can rely on a voice action or touch.</p>
 
-<p class="try"><strong>Try this:</strong> Make a list of all the situations a user would find your app useful. What do they have in common? Same location? Time of day? Certain physical activities? You will most likely come up with several different situations - that’s a good sign, because it means that you can specialize your cards to those situations. Remember that the user always has the option of completely muting your stream cards if they feel they aren’t relevant enough.</p>
+<p class="try"><b>Try this:</b> Make a list of all the situations a user would find your app useful. What do they have in common? Same location? Time of day? Certain physical activities? You will most likely come up with several different situations - that’s a good sign, because it means that you can specialize your cards to those situations. Remember that the user always has the option of completely muting your stream cards if they feel they aren’t relevant enough.</p>
 
 
-<p>[image] </p>
-<p class="img-caption">An app that offers to check in users could appear in the stream suggesting the most likely place nearby, after a certain amount of time.</p>
 
+<h2 id="Fast">Do one thing, really fast</h2>
 
-<h2>Do one thing, really fast</h2>
 <p>While users will engage with your app for only a few seconds at time, they'll use it many times throughout the day. A well-designed stream card carries one bit of information and potentially offers a few action buttons when the user swipes over.</p>
 
-<p class="try"><strong>Try this:</strong> How many bits of information is there in your design? Is everything absolutely necessary, or could you split it up into separate cards? If you’re designing a card, don’t forget that you can use multiple pages.</p>
+<p class="try"><b>Try this:</b> How many bits of information is there in your design? Is everything absolutely necessary, or could you split it up into separate cards? If you’re designing a card, don’t forget that you can use multiple pages.</p>
 
 
-<h2>Design for the corner of the eye</h2>
+<h2 id="CornerOfEye">Design for the corner of the eye</h2>
+
 <p>The longer the user is looking at your app, the more you are pulling them out of the real world. Thinking about how to design your app for glanceability can vastly help the user get full value from your app and quickly go back to what they were doing.</p>
 
-<p class="try"><strong>Try this:</strong> To view your app with your peripheral vision, try focusing on your knuckles while your watch is displaying the app. Do you get a sense of what it is trying to do? Is it distinguishable from other apps? Does the background image help conveying the message? Does it use photos or a distinct shape and color?</p>
+<p class="try"><b>Try this:</b> To view your app with your peripheral vision, try focusing on your knuckles while your watch is displaying the app. Do you get a sense of what it is trying to do? Is it distinguishable from other apps? Does the background image help conveying the message? Does it use photos or a distinct shape and color?</p>
 
-<h2>
-Don’t be a constant shoulder tapper</h2>
+
+<h2 id="Tapper">Don’t be a constant shoulder tapper</h2>
+
 <p>A watch constantly touches the user’s skin. Being this intimate, you want to buzz the watch fewer times than you’re used to on the phone.</p>
 
-<p class="try"><strong>Try this:</strong> Next time you’re in a conversation, imagine someone tapping you your shoulder, interrupting you with the information you want your app to deliver. If the information delivered did not justify suspending a conversation, you should not make the notification interruptive.</p>
\ No newline at end of file
+<p class="try"><b>Try this:</b> Next time you’re in a conversation, imagine someone tapping you your shoulder, interrupting you with the information you want your app to deliver. If the information delivered did not justify suspending a conversation, you should not make the notification interruptive.</p>
\ No newline at end of file
diff --git a/docs/html/design/wear/structure.jd b/docs/html/design/wear/structure.jd
index caeb119..f5ed49d 100644
--- a/docs/html/design/wear/structure.jd
+++ b/docs/html/design/wear/structure.jd
@@ -1,78 +1,69 @@
-page.title=App Structure for Wear
+page.title=App Structure for Android Wear
 @jd:body
 
 
-<p>As outlined in the <a href="{@docRoot}design/wear/creative-vision.html">Creative Vision</a>,
-Android Wear apps do not adhere to the traditional mobile app model of touching an icon to launch into a self-contained experience. Rather, it is useful to think about the different spaces in the Android Wear UI and how your app might present itself across these spaces. For example, a typical app might begin by showing a notification card in the stream at a contextually relevant moment, then jump into a custom full screen UI for a micro-interaction, or maybe open the cue card to capture voice input that is then relayed back to the in-stream card.</p>
+<p>Users are used to tapping icons to launch apps. Android Wear is different. A typical Wear app adds a card to the stream at a contextually relevant moment. It might have a button that opens a full screen view for a fast micro interaction, like below, but it just as well might not.
+</p>
 
-<p>It’s important to make some fundamental decisions about how your users will interact with your app. There are a number of ways that functionality can manifest itself in Android Wear, and it is important to choose the places that provide maximum value and ease of use.</p>
+<img src="{@docRoot}design/media/wear/appstructuresample.png" alt="" />
 
-<p>For example, application functionality might show up in the following ways:</p>
+<p>These are the building blocks, ordered by simplicity. You can use one of them or some of them, but we strongly recommend not building apps the user has to launch and quit before thinking really hard about how you could react to a specific location, activity, time of day, or something happening in the cloud.</p>
+
 
 <ul>
-  <li>As a <strong>card in the main context stream</strong>:
+  <li><strong>Contextual card in the stream</strong>:
   <ul>
-    <li><strong>Bridged notifications</strong> are pushed to the wearable from the connected handheld (a phone or tablet) using the standard Android notifications framework. In general, bridged notifications mirror what’s happening on the handheld and use one of a predefined layout templates. Example: new message notification.
-    <li><strong>Contextual notifications</strong> are like smart notifications. They are generated locally on the wearable and appear at contextually relevant moments specificed by the app developer. Contextual notifications allow more freedom of control, allowing for custom layouts and dynamic updating of card contents. Example: live updating exercise stats.
+    <li><a href="#Bridged"><strong>Bridged notifications</strong></a> are pushed to the wearable from the connected handheld such as new message notifications, using standard Android notifications. These require little or no code on the wearable.
+    <li><a href="#Contextual"><strong>Contextual notifications</strong></a> are generated locally on the wearable and appear at contextually relevant moments such as an exercise card that appears when you’re going on a run. You can do more with this kind of card than with a notification bridged from the handheld.
   </ul>
   </li>
-  <li>As a <strong>full screen UI</strong> that temporarily overlays on top of the context stream:
+  <li><strong>Full screen UI app</strong>:
   <ul>
-    <li>The <strong>2D Picker</strong> is a simple design pattern (available in the SDK as a prebuilt component) aimed at asking the user to select from a set of items. This is a common interaction and a familiar pattern, so use of the familiar 2D Picker pattern is encouraged wherever possible. Example: choose from a set of artists and albums to play.
-    <li><strong>Custom layouts</strong> are also possible where apps need to extend beyond the basic card/stream metaphor. These apps should be distinctly separate from the core user experience in both appearance and interaction.</li>
+    <li><a href="#2DPicker"><strong>2D Picker</strong></a> is design pattern that allows the user to select from a set of items, such as choosing artists and then albums. We recommend using this pre-built component from the SDK whenever relevant.
+    <li><a href="#Custom"><strong>Custom layouts</strong></a> are also possible where apps need to extend beyond the basic card/stream metaphor.</li>
   </ul>
   </li>
 </ul>
 
-
-<p>Apps can also open the cue card to capture voice input.</p>
-
-<p>Note that the different approaches above are listed in order of complexity. When designing your interactions, try to achieve them with the simplest approach possible. If your needs are more involved, move to the next level of complexity.</p>
-
 <p>Many applications will consist of a combination of these views, possibly with connections between them. For example, a contextual card may have an action that launches a more immersive experience. Inversely, an immersive experience may result in a card being added to the stream.</p>
 
-<p>Think of these different components as building blocks that can be snapped together into a single user flow. Avoid single monolithic full screen UIs that need to be launched and quit. Place simple notifications and ongoing information in the stream, and jump in and out of simple full screen activities to complete quick tasks before returning to the stream.</p>
-
-<p>In this section we will look at these different approaches and how combine them to create the best experience for your users.</p>
-
 
 <h2 id="Bridged">Bridged Notifications</h2>
 
-<div class="framed-wear-square-small" style="float:right;margin:0 -22px 60px 40px">
-  <img src="{@docRoot}design/media/wear/bridgednotifications.jpg">
-</div>
+<img src="{@docRoot}design/media/wear/bridgednotifications.jpg" height="147" style="float:right;margin:0 0 20px 20px" alt="">
+<img src="{@docRoot}design/media/wear/Bluebird.png" height="147" style="float:right;margin:0 0 20px 40px" alt="">
 
-<p>Bridged notifications are the simplest way of having content appear on an Android wearable. Since cards in the Android Wear stream are synced from the notifications on your connected handheld, any notifications created there automatically appear on Android Wear. Where appropriate, make sure to use the new APIs in the support library that enhance your app's notifications with features such as voice replies and notification pages.</p>
+<p>This is the simplest way to get on Android Wear. In fact, your app already does this if it uses notifications. You can add Wear-specific features like extra pages and voice replies by using the new notification APIs. </p>
+
+<a class="notice-developers left" style="clear:none" href="{@docRoot}training/wearables/notifications/creating.html">
+  <div>
+    <h3>Developer Docs</h3>
+    <p>Creating a Notification</p>
+  </div>
+</a>
+
+
+<h2 id="Contextual" style="clear:both">Contextual Notifications</h2>
+
+
+<img src="{@docRoot}design/media/wear/context_workout.png" width="323" height="147" style="float:right;margin:0 0 20px 40px;clear:right" alt="" />
+<img src="{@docRoot}design/media/wear/context_lights.png" width="323" height="147" style="float:right;margin:0 0 20px 40px;clear:right" alt="" />
+
+<p>This is what Android Wear does best; showing users information just when they need it.</p>
+
+<p>Here’s how it works: Your app knows when it is relevant for the user, and when it happens, you trigger a contextual notification. Maybe you’re building a running app that’s relevant when the user is running. Maybe it’s a museum guide that’s relevant when the user is visiting a particular museum. Check out the design principles for more on thinking about your app contextually. </p>
+
+<p>Getting contextual triggering right is one of the most impactful things you can do to craft a great user experience. </p>
+
+<p>The easiest way to do this is to use standard templates for Android notifications. If you decide to make your own ActivityView, we strongly recommend you take a look at the <a href="{@docRoot}design/wear/style.html">Style</a> guide to make sure you stay consistent with the rest of the device. </p>
+
+<p>Don’t forget to test your triggering thoroughly. Triggering too often can be so annoying that users might end up blocking all your notifications. </p>
 
 
 
-<h2 id="Contextual">Contextual Notifications</h2>
+<h2 id="2DPicker">2D Picker</h2>
 
-<p>Displaying information on contextual cards is at the core of the Android Wear user experience. Cards with focused trigger criteria appear at just the right time, delighting and assisting the user with timely, useful content. Refer to the Design principles section for details on how to think about triggering cards, and the UI overview section for a breakdown of the familiar system UI components that make up an entry in the context stream.</p>
-
-<p>An important aspect of creating contextual notifications is defining trigger conditions: what is the specific scenario in which your notification should appear? Think about using all sensor information available to you -- time, location, movement, identity, user habits and patterns, interaction with nearby devices, and more -- and describe the specific combination of sensor readings that should result in your app presenting itself.</p>
-
-
-<img src="{@docRoot}design/media/wear/contextualnotification.png" width="500" alt="" />
-
-
-<p>For example, imagine you were building a running app. If the user is standing at the beginning of their regular running trail, at the time that they often go for a run, and we detect a running activity... they are probably going for a run! This would be a great time to present a contextual card that offers to track their run.</p>
-
-<p>Putting effort into getting your contextual triggering just right is one of the most impactful things you can do to create a delightful experience for your users.</p>
-
-<p>You may use the standard Android notifications framework to create cards using a range of provided templates, or draw your own ActivityView inside cards for a custom card layout. Make sure to refer to the Style section to make sure your custom ActivityView layouts are sympathetic to the overall design of cards in the stream. Use ActivityViews to create custom card layouts that are stylistically consistent with neighboring cards in the stream; do not invent entirely new or conflicting UI patterns inside cards.</p>
-
-<p>Contextual cards are ideal for situations where it may be useful to push information to the user, when the information may be useful on an ongoing basis or referred back to, or when context strongly indicates that the information is useful. Refer to the section on Respecting Users Attention in the Design Principles section for details on targeted triggering. Triggering too often or in unsuitable contexts will result in users being annoyed by your app.</p>
-
-
-
-<h2 id="Picker">2D Picker</h2>
-
-<p>The 2D Picker design pattern (available as the GridViewPager component) is useful for showing a range of options or asking a user to make a quick selection. Google search results on Android Wear are a great example of the GridViewPager pattern in action.</p>
-
-<p>A 2D Picker is called up as an overlay on the main UI by tapping a card or button, or through a voice action. It preserves the same look and feel as the main context stream, giving users a familiar and predictable set of interaction patterns to rely on.</p>
-
-<p>On Android Wear, the basic hierarchy is vertical-then-horizontal, never horizontal-then-vertical, with a recommended vertical limit of five cards. Each vertical slot may consist of one card, as in the Google results case, or multiple cards which may be swiped horizontally.</p>
+<p>The 2D Picker design pattern (available as the <a href="{@docRoot}training/wearables/apps/layouts.html#UiLibrary">GridViewPager component</a>) is useful for showing a range of options or asking a user to make a quick selection. Google search results on Android Wear are a great example of the GridViewPager pattern in action.</p>
 
 <img src="{@docRoot}design/media/wear/1D_picker.png" alt="" width="499px" />
 <p class="img-caption">This pattern can be used to present a single vertical list, or a “1D Picker”</p>
@@ -80,37 +71,60 @@
 <img src="{@docRoot}design/media/wear/2D_picker.png" alt="" width:760px" />
 <p class="img-caption">It can also be used as a 2D matrix of options, as a way of presenting categorized options.</p>
 
-<p>This flexibility means that developers can choose to present a one or two-dimensional set of options. For example, a music app could use a vertical list to present a list of albums by a given artist (one dimension of options), and it could additionally allow each album slot to be horizontally swipeable to also choose a song from each album (a second dimension of options).</p>
 
-<p>Do not add buttons or pages to horizontal 2D Picker rows; rows should only be used to present a list or grid of similar options in this context. Provide a clear call to action on the card using the Action cards pattern detailed in the <a href="{@docRoot}design/wear/patterns.html">UI Patterns</a> guide.</p>
+<img src="{@docRoot}design/media/wear/2d_picker_indicated.png" alt="" width="760px" />
+<p class="img-caption">Navigation should be vertical-then-horizontal, not horizontal-then-vertical, and limit the the vertical set to around five cards.</p>
 
+
+<h3>Actions</h3>
+<p>For actions on each cards, use the <a href="{@docRoot}design/wear/patterns.html#Actions">Action cards pattern</a>.</p>
+
+
+<h3>Exiting</h3>
 <p>2D Picker should be automatically dismissed when a selection is made. It may also be exited by swiping back down on the first card, or by swiping left to right on a leftmost card.</p>
 
-<p>The simplicity of individual cards within a 2D Picker is a feature. Remember that in many cases the user may be on the go or attempting to complete a task as quickly as possible. As such, micro-interactions and familiar input mechanism are paramount, and using the already-familiar pattern of vertically-then-horizontally oriented cards gives users exactly what they want with as little fuss as possible. Strive to minimize the number of results or options that you present. Show the most popular or repeatedly-used options at the top of the list of cards to avoid scrolling. Learn the user's preferences and use context detection to put the most likely option for any given situation at the top. In general, optimize for fast task completion over excessive customization.</p>
+<h3>Making it fast</h3>
+<p>A few of our favorite tips on how to make the 2D picker really fast for your users:</p>
+<ul>
+<li>Minimize the number of cards</li>
+<li>Show the most popular card at the top </li>
+<li>Keep the cards extremely simple</li>
+<li>Optimize for speed over customization</li>
+
+</ul>
 
 
 
-<h2 id="Custom">Custom Layouts</h2>
+<h2 id="Custom">Breaking out of the card (with custom layouts)</h2>
 
-<p>Some interactions may require a broader range of input mechanisms than is possible within the limitations of a card-based UI. For example, an app that allows for location selection may require the user to swipe in many directions before tapping to drop a pin. In cases like this, it is recommended to momentarily launch out of the context stream UI and present an immersive, full screen app with a custom layout.</p>
-
-<p>Custom full screen apps provides the benefit of flexibility: you can launch your own Android activity that takes up the entire screen, and capture all touch events, making a wide range of UIs possible.</p>
-
-<img src="{@docRoot}design/media/wear/customlayout.jpg" alt="" width="760px" />
+<p>There are some things you can’t do on a card. Swiping in many directions on a map or a joystick are a few examples. In those cases it might be good idea to momentarily go full screen.</p>
 
 
-<p>However, be cautious of making this the default way of accessing your app’s functionality. Users will thank you for presenting your content in the familiar, simple environment of the context stream if it is possible to do so. Only enter full screen mode when the interactions required are not possible using the card UI. Full screen is a modal state to be entered for the purpose of achieving a specific task, and in most cases should be easily and quickly exited. You should use full screen apps to achieve a single, quick task within a broader user flow that hinges off the Context Stream. A great full screen experience will present itself quickly, ask for some user input, and then self-quit back to the stream.</p>
+<a class="notice-developers" href="{@docRoot}training/wearables/apps/index.html">
+  <div>
+    <h3>Developer Docs</h3>
+    <p>Creating Wearable Apps</p>
+  </div>
+</a>
 
-<p>To avoid confusion, avoid using the specific styles and idioms of the context stream when designing immersive experiences. If you find yourself replicating the structure of the card layout, your should probably be using a 2D Picker. Make your immersive experience visually distinct. However, still adhere to the <a href="{@docRoot}design/wear/principles.html">Design Principles</a>, which apply universally to Android Wear interfaces.</p>
+<img src="{@docRoot}design/media/wear/customlayout.png" alt="" width="760px" />
 
-<p>Because Android wearables do not feature a home or back button, exiting the application at the appropriate time is the responsibility of the app developer. Exiting always leads back to the context stream. Where possible, exit automatically or present the option to exit at logical break points using acknowledge/cancel buttons. For example:</p>
+<h3>When to go full screen</h3>
+<p>We highly recommend only going full screen when you can’t do what you want on a card, and quickly exit back to the stream the moment you’re done. That way your app will feel like an integrated part of the system.</p>
 
-<ol>
-<li>A map view that allows the user to slide a map to drop a pin on a location should automatically exit when the pin has been placed.</li>
-<li>A short game should automatically exit back to the stream at the end of each game.</li>
-<li>A drawing app should display the option to exit after 5 seconds of inactivity.</li>
-</ol>
+<h3>Be distinct</h3>
+<p>Your full screen design shouldn’t look too much like the card stream or it could confuse users. The 2D picker is always available if you need a card-like UI.</p>
 
-<p>Even with logical exit points like these, some cases may exist where the user may want to immediately initiate an exit. This may be particularly common in apps of longer duration. In all cases, the developer should <strong>present the option to quit the app on long press</strong> using DismissOverlayView. Your design should long press for the sole purpose of prompting to quit.</p>
+<h3>Automatically exiting</h3>
+<p>Many devices don’t have back or home buttons, so exiting is your responsibility as the app designer. Here’s a few examples of natural exits:</p>
+<ul>
+  <li>A map that asks the user to drop a pin should exit when it happens</li>
+  <li>A short game can exit when the game finishes</li>
+  <li>A drawing app can finish after 5 seconds of inactivity.</li>
+</ul>
 
-<p>Seamlessly and fluidly moving between the context stream and immersive mode makes your app feel like an integrated part of the Android Wear experience.</p>
\ No newline at end of file
+<h3>Manually exiting</h3>
+<p>Even with logical exit points like these, some cases may exist where the user may want to immediately exit. This may be common in apps that are used for a longer while. In all cases, the developer should present the option to quit the app on long press using 
+<a href="{@docRoot}training/wearables/apps/layouts.html#UiLibrary"><code>DismissOverlayView</code></a>. Your design should reserve long press for the sole purpose of prompting to quit.</p>
+
+
diff --git a/docs/html/design/wear/style.jd b/docs/html/design/wear/style.jd
index ed39bd6..948b934 100644
--- a/docs/html/design/wear/style.jd
+++ b/docs/html/design/wear/style.jd
@@ -1,57 +1,69 @@
-page.title=Style for Wear
+page.title=Style for Android Wear
 @jd:body
 
 
 <p>Here are a number of design considerations to bear in mind that are particular to Android Wear.</p>
 
-<h2 id="ScreenSize">Screen Size</h2>
+
 
 <img src="{@docRoot}design/media/wear/circle_message2.png" height="200"
-   style="float:right;margin:0 0 20px 60px">
+   style="float:right;margin:32px 0 50px 40px;">
 
 <img src="{@docRoot}design/media/wear/fitness.png" height="200"
-  style="float:right;margin:0 0 20px 60px">
+  style="float:right;margin:32px 0 50px 40px;">
+
+<h2 id="ScreenSize">Screen Size</h2>
 
 <p>Be mindful of different device sizes and shapes. Wearable devices are a form of fashion and expression for their owners, and so Android Wear supports  a variety of forms. Most of the complexities of supporting these different devices is taken care of at a system level, but bear in mind different screen types when designing custom full screen apps.</p>
 
-<p>Use the Android Wear emulator to test both square and round devices, and note that <code>WatchViewStub</code> is available to activities to detect whether a square or round device is being used.</p>
+<p>Use the Android Wear emulator to test both square and round devices, and note that <a
+href="{@docRoot}training/wearables/apps/layouts.html#UiLibrary"><code>WatchViewStub</code></a> is available to activities to detect whether a square or round device is being used.</p>
 
 
 
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
 
-<h2 id="Assets" style="clear:both">Specific Assets Required</h2>
+  <img src="{@docRoot}design/media/wear/assets_specifics.png" width="300"
+    style="margin:32px 0 20px;">
+  </div>
+  <div class="layout-content-col span-7">
+  <h2 id="Assets" style="clear:both">Specific Assets Required</h2>
 
-<img src="{@docRoot}design/media/wear/assets_specifics.png" width="300"
-  style="float:left;margin:0 60px 20px 0">
-
-<p>A core set of standard assets may need to be provided depending on your card design: app icon, background image or images, action icons, actions confirmation animation. Of course, your specific design may necessitate other assets. Background image should be provided in landscape format at least 600px width for notifications that include pages of cards, since the system automatically adds a parallaxing effect.</p>
-
-
-
-<h2 id="PeekCard" style="clear:both">Peek Card Readability</h2>
-
-<img src="{@docRoot}design/media/wear/peek_card.png" width="300"
-  style="float:left;margin:0 60px 20px 0">
-
-<p>Test your card layout to ensure that useful information is conveyed in the peek state on the Home screen. The main message of the card should be readable in the peek state, particularly for contextual cards. Content that requires an interaction to be read, for example a long message, should be cropped appropriately to provide an affordance to the user to swipe the card to read more.</p>
-
-
-
-<h2 id="InfoDensity" style="clear:both">Low Information Density</h2>
-
-<div class="framed-wear-square-small" style="float:right;margin:0 0 40px 60px">
-  <img src="{@docRoot}design/media/wear/low_info_card.png">
+  <p>A core set of standard assets may need to be provided depending on your card design: app icon, background image or images, action icons, actions confirmation animation. Of course, your specific design may necessitate other assets. Background image should be provided in landscape format at least 600px width for notifications that include pages of cards, since the system automatically adds a parallaxing effect.</p>
+  </div>
 </div>
 
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+  <h2 id="PeekCard" style="clear:both">Peek Card Readability</h2>
+
+  <p>Test your card layout to ensure that useful information is conveyed in the peek state on the Home screen. The main message of the card should be readable in the peek state, particularly for contextual cards. Content that requires an interaction to be read, for example a long message, should be cropped appropriately to provide an affordance to the user to swipe the card to read more.</p>
+  </div>
+  <div class="layout-content-col span-6">
+
+  <img src="{@docRoot}design/media/wear/peek-card.png" width="300"
+    style="margin:12px 0 0 20px">
+  </div>
+</div>
+
+
+
+  <img src="{@docRoot}design/media/wear/low_info_card.png" width="147" height="147"
+  style="float:right;margin:29px 0 20px 40px">
+
+<h2 id="InfoDensity" style="margin-top:0" >Low Information Density</h2>
+
 <p>Cards should be designed to be glanceable in a split second, just like reading the time on a traditional watch. In most cases a pairing of an icon and value, or a title and short caption should be enough to convey a meaningful message. Note that the background photo should also be used to convey information; backgrounds that change to reflect and support the primary message in the card work great. For example, in the case illustrated above a suitable background image is chosen to reflect severity of the current traffic conditions. This is not just a nice piece of attention to detail; the background actually reinforces the message and makes the content more glanceable.</p>
 
 
-<h2 id="Chunks" style="clear:both">Separate Information into Chunks</h2>
+<img src="{@docRoot}design/media/wear/separate_info_cards.jpg" height="147"
+  style="float:right;margin:29px 0 20px 40px">
 
-<img src="{@docRoot}design/media/wear/separate_info_cards.jpg" width="400"
-  style="float:left;margin:0 60px 20px 0">
+<h2 id="Chunks">Separate Information into Chunks</h2>
 
-<p>In cases where additional information is absolutely necessary, don’t crowd out a card layout to the point where glanceability is affected. Instead, add an additional page (or multiple pages, if needed) to the right of the main card in the stream to which the user can swipe for more information. See also “Continuing activities on phone”, below.</p>
+<p>In cases where additional information is absolutely necessary, don’t crowd out a card layout to the point where glanceability is affected. Instead, add an additional <a href="{@docRoot}design/wear/patterns.html#Pages">page</a> (or multiple pages, if needed) to the right of the main card in the stream to which the user can swipe for more information. See also <a
+href="{@docRoot}design/wear/patterns.html#Continuing">Continuing activities on phone</a>.</p>
 
 
 <h2 id="KeepMinimum" style="clear:both">Keep Notifications to a Minimum</h2>
@@ -59,39 +71,39 @@
 <p>Don’t abuse the user’s attention. Active notifications (that is, those that cause the device to vibrate) should only be used in cases that are both timely and involve a contact, for example receiving a message from a friend. Non-urgent notifications should be silently added to the Context Stream. See also the general Android Notifications Guidelines.</p>
 
 
-<h2 id="Typography" style="clear:both">Use Clear, Bold Typography</h2>
-
-<div class="framed-wear-square-small" style="float:right;margin:0 0 60px 40px">
-  <img src="{@docRoot}design/media/wear/clear_bold_type.jpg">
-</div>
-
-<p>The system font is Roboto Condensed, with Regular and Light variants. Text should adhere to the size and color recommendations (see the UI Toolkit in the Downloads section). In general, text should be displayed as large as possible. Your goal should be to convey maximum information with minimum fuss.</p>
 
 
-<h2 id="Branding" >Use Consistent Branding and Color</h2>
+<img src="{@docRoot}design/media/wear/clear_bold_type.jpg" height="147"
+  style="float:left;margin:19px 40px 20px 0">
+
+<h2 id="Typography" >Use Clear, Bold Typography</h2>
+
+<p>The system font is Roboto Condensed, with Regular and Light variants. Text should adhere to the size and color recommendations (see the UI Toolkit in the <a href="{@docRoot}design/downloads/index.html#Wear">Downloads</a> page). In general, text should be displayed as large as possible. Your goal should be to convey maximum information with minimum fuss.</p>
+
+
+<h2 id="Branding" style="clear:both" >Use Consistent Branding and Color</h2>
 
 <p>The app icon is used to identify and brand your application. The icon is optional but when present always appears in the same location, overhanging the top edge of the card at the right. Note that app icons or branding should not be displayed in the background photo, which is reserved to display an image relevant to the information on the card.</p>
 
 
-<h2 id="Copywrite" style="clear:both">Copywrite Sparingly</h2>
+<img src="{@docRoot}design/media/wear/copywrite.png" height="147"
+  style="float:left;margin:19px 40px 20px 0">
 
-<div class="framed-wear-square-small" style="float:right;margin:0 0 60px 40px">
-  <img src="{@docRoot}design/media/wear/copywrite.png">
-</div>
+<h2 id="Copywrite" >Copywrite Sparingly</h2>
 
 <p>Omit needless text. Design for glanceability, not reading. Use words and phrases, not sentences. Use icons paired with values instead of text wherever possible. Text strings should be as concise as possible, and long pieces of text will be truncated to fit on a single card.</p>
 
 
-<h2 id="BeDiscreet" >Be Discreet if Necessary</h2>
+<h2 id="BeDiscreet" style="clear:both" >Be Discreet if Necessary</h2>
 
 <p>Wearables are personal devices by nature, but they are not completely private. If your notification serves content that may be particularly sensitive or embarrassing (such as notifications from a dating app or a medical status report), consider not displaying all of the information in a peek card. A notification could place the sensitive information on a second page that must be swiped to, or an application could show different amounts of detail in peek and focused card positions.</p>
 
 
-<h2 id="ConfirmAnim" style="clear:both">Confirmation Animations</h2>
+  <img src="{@docRoot}design/media/wear/confirmation.png" height="147"
+  style="float:left;margin:29px 40px 20px 0">
 
-<div class="framed-wear-square-small" style="float:left;margin:0 40px 40px 0 ">
-  <img src="{@docRoot}design/media/wear/confirmation.png">
-</div>
+
+<h2 id="ConfirmAnim">Confirmation Animations</h2>
 
 <p>If your app allows the user to perform an action, it is necessary to provide positive feedback. Show a generic confirmation animation or create your own. A confirmation animation is an opportunity to express your app’s character and insert a moment of delight for your user. Keep animations short (less than 1000ms) and simple. Animating the confirmation icon is an effective way of transitions the user to a new state after completing an action.</p>
 
@@ -100,3 +112,4 @@
 
 
 
+
diff --git a/docs/html/images/home/auto-wordmark.png b/docs/html/images/home/auto-wordmark.png
new file mode 100644
index 0000000..027dfca
--- /dev/null
+++ b/docs/html/images/home/auto-wordmark.png
Binary files differ
diff --git a/docs/html/images/home/auto.png b/docs/html/images/home/auto.png
index 7ea01b0..4ce882a 100644
--- a/docs/html/images/home/auto.png
+++ b/docs/html/images/home/auto.png
Binary files differ
diff --git a/docs/html/images/home/tv-wordmark.png b/docs/html/images/home/tv-wordmark.png
new file mode 100644
index 0000000..e7660ac
--- /dev/null
+++ b/docs/html/images/home/tv-wordmark.png
Binary files differ
diff --git a/docs/html/images/home/tv.png b/docs/html/images/home/tv.png
index 3cf2034..7208a99 100644
--- a/docs/html/images/home/tv.png
+++ b/docs/html/images/home/tv.png
Binary files differ
diff --git a/docs/html/images/home/wear-wordmark.png b/docs/html/images/home/wear-wordmark.png
new file mode 100644
index 0000000..e645887
--- /dev/null
+++ b/docs/html/images/home/wear-wordmark.png
Binary files differ
diff --git a/docs/html/images/home/wear.png b/docs/html/images/home/wear.png
index dfaded7..e6602fd 100644
--- a/docs/html/images/home/wear.png
+++ b/docs/html/images/home/wear.png
Binary files differ
diff --git a/docs/html/images/material.png b/docs/html/images/material.png
new file mode 100644
index 0000000..981359b
--- /dev/null
+++ b/docs/html/images/material.png
Binary files differ
diff --git a/docs/html/images/resource-card-android-studio.png b/docs/html/images/resource-card-android-studio.png
new file mode 100644
index 0000000..0f483df
--- /dev/null
+++ b/docs/html/images/resource-card-android-studio.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 2f01538..253a7a5 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -6,43 +6,37 @@
 
 @jd:body
 
-<!-- Top full-bleed carousel -->
-<div class="home-new-carousel-1" style="margin-top:40px">
+<div class="home-new-carousel-1">
   <div class="fullscreen-carousel-content">
     <div class="vcenter">
       <div class="wrap clearfix">
 
         <div class="static resource-flow-layout wrap col-16">
           <div class="resource resource-card resource-card-18x6">
-            <div class="card-bg" style="background-image: url('/preview/images/l-dev-prev.png');"></div>
-            <div class="card-info">
-              <div class="section"></div>
-              <div class="title">Android L Developer Preview</div>
-              <div class="description ellipsis" style="height: 285px;">
-                <div class="text" style="height: auto;">
-                  <p style="font-size:16px;">Get an early look at the next Android release and
-                    start using new APIs so your apps are ready when the platform officially launches.</p>
-                  <p>
-                  <a href="{@docRoot}preview/index.html" class="landing-button landing-secondary">Learn more</a></p>
-                </div>
-              </div>
+
+      <div class="landing-section-header">
+            <div class="col-10"><img src="{@docRoot}preview/images/l-dev-prev.png"
+            style="margin:40px 60px 0 20px"></div>
+            <div class="col-5" style=" margin-top:70px ">
+            <h3 stye="font-weight:300;">L Developer Preview</h3>
+            <p>The L Developer Preview lets you design and develop against the next major
+            release of Android. Take the time to test and build your app before the platform
+            officially launches. </p>
+            <a href="{@docRoot}preview/index.html" class="landing-button landing-primary">Learn More</a>
             </div>
           </div>
+          </div>
         </div>
-
-        <div class="resource-widget resource-flow-layout wrap col-16 no-section"
-          data-query="collection:index/primary"
-          data-resourceStyle="card"
-          data-sortOrder="-timestamp"
-          data-maxResults="3"
-          data-cardSizes="6x2,6x2,6x2">
-        </div> <!-- end .resource-widget -->
+       <h2>&nbsp;</h2>
+        <div style="margin-top:20px" class="resource-widget resource-flow-layout wrap col-16
+        no-section" data-query="collection:index/primary" data-resourcestyle="card"
+        data-sortorder="-timestamp" data-maxresults="3" data-cardsizes="6x2,6x2,6x2"></div> <!-- end .resource-widget -->
       </div> <!-- end .wrap -->
     </div> <!-- end .vcenter -->
   </div> <!-- end .fullscreen-carousel-content -->
 </div> <!-- end .fullscreen-carousel -->
 
-<div class="actions-bar" style="margin-top:30px">
+<div class="actions-bar" style="margin-top:20px">
   <div class="wrap">
     <div class="actions">
       <div><a href="{@docRoot}sdk/index.html">Get the SDK</a></div>
@@ -59,26 +53,29 @@
   <div class="landing-section">
     <div class="wrap">
       <div class="landing-section-header">
-        <div class="landing-h1">Develop for Multiple Form Factors</div>
+        
+            <div class="landing-h1" style="margin-top:0px">Build for a Multi-Screen World</div>
         <div class="landing-subhead" style="margin-top: 20px;">
-          Android runs on hundreds of millions of handheld devices around the world, <br />
+          Android runs on hundreds of millions of handheld devices around the world, <br>
           and it now supports these exciting, new form-factors.
         </div>
       </div>
-      <div class="landing-body" style="margin-top: 80px;">
+      <div class="landing-body" style="margin-top: 50px;">
         <div class="landing-breakout cols">
           <div class="col-3-wide">
+              <img src="{@docRoot}images/home/wear-wordmark.png">
               <img src="{@docRoot}images/home/wear.png">
-              <p class="landing-small" style="margin-top:30px">
+              <p class="landing-small">
                 Provide information on-the-go for your users, whenever they need it.
             </p>
             <p class="landing-small">
               <a href="{@docRoot}wear/index.html">Learn about Android Wear</a>
             </p>
           </div>
-          <div class="col-3-wide">            
+          <div class="col-3-wide">
+              <img src="{@docRoot}images/home/tv-wordmark.png">
              <img src="{@docRoot}images/home/tv.png">
-              <p class="landing-small" style="margin-top:30px">
+              <p class="landing-small">
                 Build your apps for the big screen and bring your content to life.
               </p>
             <p class="landing-small">
@@ -86,9 +83,10 @@
 
             </p>
           </div>
-          <div class="col-3-wide">            
+          <div class="col-3-wide">
+              <img src="{@docRoot}images/home/auto-wordmark.png">
               <img src="{@docRoot}images/home/auto.png">
-              <p class="landing-small" style="margin-top:30px">
+              <p class="landing-small">
                 Extend your music apps to automobile
                 entertainment systems.
              </p>
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index a92236e..cd49ace 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -2,9 +2,9 @@
   "index/primary": {
     "title": "",
     "resources": [
-      "distribute/essentials/quality/tablets.html",
-      "distribute/engage/game-services.html",
-      "distribute/googleplay/edu/about.html" 
+      "training/building-wearables.html",
+      "preview/material/index.html",
+      "sdk/installing/studio.html" 
     ]
   },
   "index/devices": {
diff --git a/docs/html/jd_extras.js b/docs/html/jd_extras.js
index 03bbea1..605af525 100644
--- a/docs/html/jd_extras.js
+++ b/docs/html/jd_extras.js
@@ -15,17 +15,6 @@
 
 DISTRIBUTE_RESOURCES = DISTRIBUTE_RESOURCES.concat([
   {
-    "title":"Android L Developer Preview",
-    "titleFriendly":"",
-    "summary":"<p style='font-size:18px;'>Get an early look at the next release and get your apps ready when the platform officially launches.</p>",
-    "url":"preview/index.html",
-    "group":"",
-    "keywords": [],
-    "tags": [],
-    "image":"preview/images/l-dev-prev.png",
-    "type":""
-  },
-  {
     "title":"Developer Registration",
     "titleFriendly":"",
     "summary":"Additional information about the registration process.",
@@ -1192,4 +1181,4 @@
     "type": "",
     "titleFriendly": ""
   }
-]);
\ No newline at end of file
+]);
diff --git a/docs/html/preview/google-play-services-wear.html b/docs/html/preview/google-play-services-wear.html
index ad8891f..ff43757 100644
--- a/docs/html/preview/google-play-services-wear.html
+++ b/docs/html/preview/google-play-services-wear.html
@@ -16,55 +16,55 @@
 <div class="col-12" id="doc-col">
 
 <h1 itemprop="name">Google Play services Preview for Wear</h1>
-      
-    
-  
 
+<div id="jd-content">
+<div class="jd-descr" itemprop="articleBody">
+<p>Google Play services 5.0  is currently being rolled out to the world.
+We usually wait to release the Google Play services SDK until the rollout completes.
+This ensures that your newly-updated apps can run on the most devices as possible.</p>
 
-  
-  <div id="jd-content">
-  <div class="jd-descr" itemprop="articleBody">
-<p>The Google Play services app is currently being rolled out to the hundreds of millions of
-Android devices and will complete in early July. Because of this, we usually wait to release the Google Play
-services SDK until all users receive the app. This guarantees that your newly-updated apps can
-run on the most devices as possible.</p>
+<p>However, if you want to develop for Android Wear now, complete the following steps to get
+special access to all the things you need to start developing, without waiting for the rollout to
+complete.</p>
 
-<p>However, if want to develop for Android Wear now, complete the following steps
-to get special access to all the things you need to start developing, without waiting
-for the rollout to complete. </p>
-
-<p class="warning"><b>Warning</b>: Do not publish any apps that use the new Google Play services
-APIs until the rollout is complete. Your apps will break on most user devices, which will
-degrade your user rating.</b>
+<p class="warning"><b>Warning</b>: Do not publish any apps that are built with Google Play services
+SDK 5.0 until the rollout is completed over the coming days.  Your apps will break on most user
+devices, which will degrade your apps’ user experience. We’ll publish an update to the
+<a href="http://android-developers.blogspot.com/">Android Developer blog</a> when the rollout is done.
 </p>
 
 <h2 style="margin-bottom: 0px;">1. Get Whitelisted for the Preview</h2><hr>
 
-<p>If you attended Google I/O, your registered Gmail account is automatically whitelisted for these
-preview resources. If you didn't attend Google I/O, sign up below to get access:</p>
+<p>If you attended Google I/O, your registered Google account is automatically whitelisted for
+these preview resources. You're done! Head to Step 2.</p>
 
-<a href="https://groups.google.com/forum/?hl=en#!forum/io14androidweardev">Get Whitelisted</a>
+<p><stong><em>If you didn't attend Google I/O</em></strong> or want to use a different account,
+click following link to
+<a href="https://groups.google.com/group/io14androidweardev/subscribe" target="_blank">join
+the Google Group</a> and get whitelisted.</p>
 
 <h2 style="margin-bottom: 0px;">2. Download Required Apps</h2><hr>
 <p>You'll need the following apps to get the most out of Android Wear:</p>
 
-
-<p>Here's a list of the apps you need:</p>
 <ul>
-<li><a href="https://play.google.com/apps/testing/com.google.android.gms">Google Play services</a>: Allows your Wear device to properly communicate with your handheld device. This is
-required to use the Android Wear Companion App.</li>
+<li><a href="https://play.google.com/apps/testing/com.google.android.gms">Google Play services</a>:
+Allows your Android Wear device to communicate with your handheld device. This is required to
+use the Android Wear app and other apps listed below.</li>
   <li><a href="https://play.google.com/apps/testing/com.google.android.wearable.app">Android Wear
-  Companion</a>: The main user app to pair a handheld to a wearable and to provide syncing
-  of notifications and data.</li>
+  Companion</a>: The app for pairing a handheld to a wearable and providing syncing of
+  notifications and data
+  </li>
   <li><a href="https://play.google.com/apps/testing/com.google.android.googlequicksearchbox">Google
-  Search</a>: A preview release of the Google Search handheld app that Wear communicates with
-  to carry out searches.</li>
-  <li><a href="https://play.google.com/apps/testing/com.google.android.keep">Google Keep</a>: To enable the "Take a note" command</li>
-  <li><a href="https://play.google.com/apps/testing/com.google.samples.apps.iosched">Google I/O 2014</a></li>
+  Search</a>: Enables searches from Android Wear</li>
+  <li><a href="https://play.google.com/apps/testing/com.google.android.keep">Google Keep</a>:
+  Supports the "Take a note" command</li>
+  <li><a href="https://play.google.com/apps/testing/com.google.samples.apps.iosched">Google I/O
+  2014</a>:
+  Supports session feedback from Android Wear</li>
  </ul>
 
-<p>To enable the preview versions of the apps, click each app link above and follow these
-instructions:</p>
+<p>To obtain these apps from Google Play, click each app link above and follow these instructions,
+preferably from your mobile browser:</p>
 
 <ol>
  <li>Click the <b>Become a Tester</b> button to opt-in to the preview version of the app. The page
@@ -73,23 +73,34 @@
  Store download page to get the app. The
  following screenshot shows how the opt-in process looks like:
 <img style="margin-top:40px" src="/preview/images/opt-in.png"></li>
- <li>When Google Play services is rolled out to all devices, go back to the app links provided
-  to opt-out of the preview versions of the apps. Check back here in a week for the status of
-  the rollout.</li>
+</ol>
+<h2 style="margin-bottom: 0px;">3. Start Building</h2><hr>
+
+<p>The Google Play services SDK is required if you want to sync and send data between wearable
+and handheld devices. To get the new SDK that is compatible with the Google Play services
+APK that you just installed, follow these steps: </p>
+
+<p class="note"><b>Note:</b> Android Studio is required for Wear development.</p>
+<ol>
+  <li>Start AVD Manager.</li>
+  <li>Update the Android SDK Tools and Platform-tools to versions 23 and 20 respectively.</li>
+  <li>Click <b>Tools > Manage Add-on Sites > User Defined Sites</b>.</li>
+  <li>Click <b>New</b>, enter
+  <code>https://dl-ssl.google.com/android/repository/addon-play-services-5.xml</code> into the
+  text field, and click <b>OK</b>.</li>
+  <li>Click Close. You should now see new emulator images that support this preview
+  release of Google Play services and the Google Play services client libraries you need to
+  start developing.</li>
+  <li><a href="{@docRoot}preview/google-play-services-preview.zip">Download</a> the Google Play
+  services reference documentation for this preview release.</li>.
 </ol>
 
-
-
-<h2 style="margin-bottom: 0px;">3. Start Building</h2><hr>
-<p>Check out the <a href="/training/building-wearables">Building Apps for Wearables</a>
+<p>When you're done here, check out the <a href="{@docRoot}training/building-wearables">Building Apps for Wearables</a>
 training classes for information on how to build for Wear.</p>
+
     </div>
-
-   
-      
-
-  </div> <!-- end jd-content -->
+</div> <!-- end jd-content -->
 </div><!-- end doc-content -->
-</div> <!-- end body-content --> 
+</div> <!-- end body-content -->
 </body>
 </html>
\ No newline at end of file
diff --git a/docs/html/preview/images/hero.jpg b/docs/html/preview/images/hero.jpg
deleted file mode 100644
index 1c52989..0000000
--- a/docs/html/preview/images/hero.jpg
+++ /dev/null
Binary files differ
diff --git a/docs/html/preview/images/material.png b/docs/html/preview/images/material.png
deleted file mode 100644
index 2d807d4..0000000
--- a/docs/html/preview/images/material.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/preview/images/notifications.png b/docs/html/preview/images/notifications.png
deleted file mode 100644
index 2fb2fea..0000000
--- a/docs/html/preview/images/notifications.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/preview/images/notifications/Action.png b/docs/html/preview/images/notifications/Action.png
new file mode 100644
index 0000000..de584a3
--- /dev/null
+++ b/docs/html/preview/images/notifications/Action.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/AntiSample1.png b/docs/html/preview/images/notifications/AntiSample1.png
new file mode 100644
index 0000000..2cb5411
--- /dev/null
+++ b/docs/html/preview/images/notifications/AntiSample1.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/AntiSample3.png b/docs/html/preview/images/notifications/AntiSample3.png
new file mode 100644
index 0000000..5780583
--- /dev/null
+++ b/docs/html/preview/images/notifications/AntiSample3.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Basic.png b/docs/html/preview/images/notifications/Basic.png
new file mode 100644
index 0000000..4ce21c48
--- /dev/null
+++ b/docs/html/preview/images/notifications/Basic.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Expanded.png b/docs/html/preview/images/notifications/Expanded.png
new file mode 100644
index 0000000..9ca260b
--- /dev/null
+++ b/docs/html/preview/images/notifications/Expanded.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/ExpandedImage.png b/docs/html/preview/images/notifications/ExpandedImage.png
new file mode 100644
index 0000000..7e58881
--- /dev/null
+++ b/docs/html/preview/images/notifications/ExpandedImage.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/ExpandedText.png b/docs/html/preview/images/notifications/ExpandedText.png
new file mode 100644
index 0000000..0361695
--- /dev/null
+++ b/docs/html/preview/images/notifications/ExpandedText.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Headsup.png b/docs/html/preview/images/notifications/Headsup.png
new file mode 100644
index 0000000..03015b1
--- /dev/null
+++ b/docs/html/preview/images/notifications/Headsup.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Largelogo.png b/docs/html/preview/images/notifications/Largelogo.png
new file mode 100644
index 0000000..e222422
--- /dev/null
+++ b/docs/html/preview/images/notifications/Largelogo.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/LockScreen.png b/docs/html/preview/images/notifications/LockScreen.png
new file mode 100644
index 0000000..083e646
--- /dev/null
+++ b/docs/html/preview/images/notifications/LockScreen.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/MusicPlayback.png b/docs/html/preview/images/notifications/MusicPlayback.png
new file mode 100644
index 0000000..58f3d0b
--- /dev/null
+++ b/docs/html/preview/images/notifications/MusicPlayback.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/ProductIcons.png b/docs/html/preview/images/notifications/ProductIcons.png
new file mode 100644
index 0000000..227c8ab
--- /dev/null
+++ b/docs/html/preview/images/notifications/ProductIcons.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Productlogos.png b/docs/html/preview/images/notifications/Productlogos.png
new file mode 100644
index 0000000..baed5ac
--- /dev/null
+++ b/docs/html/preview/images/notifications/Productlogos.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/ReplyAction.png b/docs/html/preview/images/notifications/ReplyAction.png
new file mode 100644
index 0000000..73c9fc6
--- /dev/null
+++ b/docs/html/preview/images/notifications/ReplyAction.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Stack.png b/docs/html/preview/images/notifications/Stack.png
new file mode 100644
index 0000000..90c6c4a
--- /dev/null
+++ b/docs/html/preview/images/notifications/Stack.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Summarise_Do.png b/docs/html/preview/images/notifications/Summarise_Do.png
new file mode 100644
index 0000000..4daaa4d
--- /dev/null
+++ b/docs/html/preview/images/notifications/Summarise_Do.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Summarise_Dont.png b/docs/html/preview/images/notifications/Summarise_Dont.png
new file mode 100644
index 0000000..4094d73
--- /dev/null
+++ b/docs/html/preview/images/notifications/Summarise_Dont.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Summary.png b/docs/html/preview/images/notifications/Summary.png
new file mode 100644
index 0000000..135de83
--- /dev/null
+++ b/docs/html/preview/images/notifications/Summary.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Summary_Do.png b/docs/html/preview/images/notifications/Summary_Do.png
new file mode 100644
index 0000000..c48bfd3
--- /dev/null
+++ b/docs/html/preview/images/notifications/Summary_Do.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/TimeSensitive.png b/docs/html/preview/images/notifications/TimeSensitive.png
new file mode 100644
index 0000000..55a9e59
--- /dev/null
+++ b/docs/html/preview/images/notifications/TimeSensitive.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/Triggered.png b/docs/html/preview/images/notifications/Triggered.png
new file mode 100644
index 0000000..c327ed2
--- /dev/null
+++ b/docs/html/preview/images/notifications/Triggered.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/WearBasic.png b/docs/html/preview/images/notifications/WearBasic.png
new file mode 100644
index 0000000..881f1e5
--- /dev/null
+++ b/docs/html/preview/images/notifications/WearBasic.png
Binary files differ
diff --git a/docs/html/preview/images/notifications/notifications_pattern_priority.png b/docs/html/preview/images/notifications/notifications_pattern_priority.png
new file mode 100644
index 0000000..137a83f
--- /dev/null
+++ b/docs/html/preview/images/notifications/notifications_pattern_priority.png
Binary files differ
diff --git a/docs/html/preview/images/opt-in.png b/docs/html/preview/images/opt-in.png
index 51754af..0f309c2 100644
--- a/docs/html/preview/images/opt-in.png
+++ b/docs/html/preview/images/opt-in.png
Binary files differ
diff --git a/docs/html/preview/images/volta.png b/docs/html/preview/images/volta.png
deleted file mode 100644
index 9125081..0000000
--- a/docs/html/preview/images/volta.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/preview/material/index.jd b/docs/html/preview/material/index.jd
index d9a276f7..9628e3a 100644
--- a/docs/html/preview/material/index.jd
+++ b/docs/html/preview/material/index.jd
@@ -1,5 +1,7 @@
 page.title=Material Design
 page.type=design
+page.image=images/material.png
+page.metaDescription=Learn how to apply material design to your apps.
 
 @jd:body
 
diff --git a/docs/html/preview/notifications.jd b/docs/html/preview/notifications.jd
new file mode 100644
index 0000000..2b75651
--- /dev/null
+++ b/docs/html/preview/notifications.jd
@@ -0,0 +1,626 @@
+page.title=Design for Notifications
+page.tags="notifications","design","L"
+@jd:body
+
+
+<p>The notification system allows users to keep informed about relevant and timely
+events in your app, such as new chat messages from a friend or a calendar event.
+Think of notifications as a news channel that alerts the user to important events as
+they happen or a log that chronicles events while the user is not paying attention -
+and one that is synced as appropriate across all their Android devices.</p>
+
+<h4 id="New"><strong>New in L</strong></h4>
+
+<p>In L, notifications receive an important structural visual and functional update:</p>
+
+<ul>
+  <li> Visual changes to notifications as part of material design</li>
+  <li> Notifications are now available on the device lockscreen, yet sensitive content can still
+  be hidden behind it</li>
+   <li> A new presentation format called Heads-up for receiving high priority notifications while
+  using the device</li>
+  <li> Cloud-synced notifications - act on a notification on your Android tablet and it is also
+  dismissed on your phone.</li>
+  <li> And starting now (in Android 4.4W, API Level 20, the platform release for Android Wear),
+  your notifications will bridge to Android Wear devices. You can extend the functionality of
+  notifications on Wear in two different ways. First, you can add speech input and canned responses
+  to Actions on Wear, allowing users to complete tasks from their wrists. Second, you can write
+  Wear apps that hook into your notifications to go even further in terms of creating interactive
+  experiences for users.</li>
+</ul>
+
+<h2 id="Anatomy">Anatomy of a notification</h2>
+
+
+<h4 id="BaseLayout"><strong>Base Layout</strong></h4>
+
+<p>At a minimum, all notifications consist of a base layout, including:</p>
+
+<ul>
+  <li> The notification's <strong>icon</strong>, symbolizing the originating app, and also potentially the kind of notification if the app has several substantially different sorts of notifications it can post</li>
+  <li> A notification <strong>title</strong> and additional <strong>text</strong></li>
+  <li> A <strong>timestamp</strong></li>
+</ul>
+<div class="figure" style="width:376px">
+  <img src="{@docRoot}preview/images/notifications/Basic.png"
+    alt="" width="376" height="281" id="figure1" />
+  <p class="img-caption">
+    <strong>Figure 1.</strong> Base layout of a handset notification
+  </p>
+</div>
+
+<div class="figure" style="width:164px">
+  <img src="{@docRoot}preview/images/notifications/WearBasic.png"
+    alt="" width="164" height="164" id="figure2" />
+  <p class="img-caption">
+    <strong>Figure 2.</strong> The same notification on Wear, with a user photo and a
+    notification icon
+  </p>
+</div>
+<p>Notifications created with {@code Notification.Builder} for versions of Android earlier than L will look and work the same in L, with only minor stylistic changes that the system handles for you.</p>
+
+
+
+<h4 id="ExpandedLayouts">Expanded layouts</h4>
+
+<p>You have the option to provide more details on notifications. You can use this to show the first few lines of a message or show a larger image preview. This provides the user with additional context, and - in some cases - may allow the user to read a message in its entirety. The user can pinch-zoom or perform a single-finger glide in order to toggle between compact and expanded layouts. For single event notifications, Android provides three expanded layout templates (text, inbox, and image) for you to re-use in your application.</p>
+
+<div class="figure" style="width:201px">
+  <img src="{@docRoot}preview/images/notifications/ExpandedText.png"
+    alt="" width="201" height="182" id="figure3" />
+</div>
+
+<div class="figure" style="width:272px">
+  <img src="{@docRoot}preview/images/notifications/Expanded.png"
+    alt="" width="272" height="121" id="figure4" />
+</div>
+
+<div class="figure" style="width:202px">
+  <img src="{@docRoot}preview/images/notifications/Stack.png"
+    alt="" width="202" height="169" id="figure5" />
+</div>
+
+<div class="figure" style="width:285px">
+  <img src="{@docRoot}preview/images/notifications/figure6.png"
+    alt="" width="285" height="124" id="figure6" />
+</div>
+
+<div class="figure" style="width:196px">
+  <img src="{@docRoot}preview/images/notifications/ExpandedImage.png"
+    alt="" width="196" height="277" id="figure7" />
+  <p class="img-caption">
+    <strong>Figure 3.</strong> A text-focused notification, an inbox notification, and a photo-centric notification, shown expanded and contracted, and with Wear equivalents for the first two.
+  </p>
+</div>
+
+<h4 id="actions"><strong>Actions</strong></h4>
+
+<p>Android has supported optional actions that are displayed at the bottom of the notification, as far back as Jelly Bean. With actions, users can handle the most common tasks for a particular notification from within the notification shade without having to open the originating application. This speeds up interaction and, in conjunction with "swipe-to-dismiss", helps users to streamline their notification triaging experience.</p>
+
+<p>Be judicious with how many actions you include with a notification. The more actions you include, the more cognitive complexity you create. Limit yourself to the fewest number of actions possible by only including the most imminently important and meaningful ones.</p>
+
+<p>Good candidates for actions on notifications are actions that:</p>
+
+<ul>
+  <li> Are essential, frequent and typical for the content type you're displaying
+  <li> Allow the user to accomplish tasks quickly
+</ul>
+
+<p>Avoid actions that are:</p>
+
+<ul>
+  <li> Ambiguous
+  <li> Duplicative of the default action of the notification (such as "Read" or "Open")
+</ul>
+
+<div class="figure" style="width:340px">
+  <img src="{@docRoot}preview/images/notifications/Action.png"
+    alt="" width="340" height="169" id="figure8" />
+  <p class="img-caption">
+    <strong>Figure 4.</strong> Calendar reminder notification with two actions
+  </p>
+</div>
+
+<div class="figure" style="width:154px">
+  <img src="{@docRoot}preview/images/notifications/ReplyAction.png"
+    alt="" width="154" height="154" id="figure8_1" />
+  <p class="img-caption">
+    <strong>Figure 5.</strong> Gmail new message notification - the actions appear to the right of the main card on Wear devices
+  </p>
+</div>
+
+<p>You can specify a maximum of three actions, each consisting of an action icon and an action name. Adding actions to a simple base layout will make the notification expandable, even if the notification doesn't have an expanded layout. Since actions are only shown for expanded notifications and are otherwise hidden, you must make sure that any action a user can invoke from a notification is available from within the associated application as well.</p>
+
+<h4 id="notifications_on_android_wear"><strong>Notifications on Android Wear</strong></h4>
+
+<p>Additionally, notifications and their actions are bridged over to Wear devices by default. Developers have control to control which notifications from bridging from the phone to the watch and vice versa. And developers can control which actions bridge as well. If your app includes actions that can't be accomplished with a single tap, either hide these actions on your Wear notification or consider hooking them up to a Wear app to allow the user to finish the action on their watch.</p>
+
+<p><strong>Bridging notifications</strong></p>
+
+<p><strong>Notifications that should be bridged</strong></p>
+
+<ul>
+  <li> New instant messages
+</ul>
+
+<p><strong>Don't bridge</strong></p>
+
+<ul>
+  <li> If a podcasting app has new episodes available for download, keep this notification on the phone.
+</ul>
+
+<p><strong>Bridging actions </strong></p>
+
+<p><strong>Actions to bridge</strong></p>
+
+<ul>
+  <li> Single tap actions such as +1, Like, Heart
+</ul>
+
+<p><strong>Actions not to bridge</strong></p>
+
+<ul>
+  <li> Actions that map to features that aren't possible on the watch
+</ul>
+
+<p><strong>Unique actions to define for Wear</strong></p>
+
+<ul>
+  <li> Quick lists of canned responses such as "Be right back"
+  <li> Open on phone
+  <li> A "Comment" or "Reply" action that brings up the speech input screen
+  <li> Actions that can launch Wear-specific apps
+</ul>
+
+<p>[Asset needed: show one or more sample Wear notifications]</p>
+
+<p><strong>Heads-up Notification</strong></p>
+
+<p>When notifications with priority set to High (see below) arrives, it is presented to users for a short period of time on the device with an expanded layout with its actions exposed. After this period of time, it retreats back to the Notification shade. If a notification is flagged as High or Max or a full-screen takeover, it gets a HUN in L.</p>
+
+
+<div class="figure" style="width:262px">
+  <img src="{@docRoot}preview/images/notifications/Headsup.png"
+    alt="" width="262" height="513" id="figure9" />
+  <p class="img-caption">
+    <strong>Figure 6.</strong> Example of a Heads-up notification (incoming phone call, high priority) coming in on top of an immersive app
+  </p>
+</div>
+
+<p><strong>Good examples of Heads-up notifications</strong></p>
+
+<ul>
+  <li> Incoming phone call when using device
+  <li> Alarm when using device
+  <li> New SMS message
+  <li> Low battery
+</ul>
+
+<h2 id="guidelines">Guidelines</h2>
+
+
+<div class="figure" style="width:366px">
+  <img src="{@docRoot}preview/images/notifications/Triggered.png"
+    alt="" width="366" height="142" id="figure10" />
+  <p class="img-caption">
+    <strong>Figure 7.</strong> Notification that shows the person who triggered it and the content they are sending you
+  </p>
+</div>
+
+<h4 id="make_it_personal"><strong>Make it personal</strong></h4>
+
+<p>For notifications of items sent by another person (such as a message or status update), include that person's image using setLargeIcon. Also attach information about the person to the notification's metadata (see EXTRA_PEOPLE).</p>
+
+<p>Your notification's main icon will still be shown, so the user can associate it with the icon visible in the status bar.</p>
+
+<h4 id="navigate_to_the_right_place"><strong>Navigate to the right place</strong></h4>
+
+<p>When the user touches the body of a notification (outside of the action buttons), open your app to the place where the user can view and act upon the data referenced in the notification. In most cases this will be the detail view of a single data item such as a message, but it might also be a summary view if the notification is stacked (see <em>Stacked notifications</em> below) and references multiple items. If in any of those cases the user is taken to a hierarchy level below your app's top-level, insert navigation into your app's back stack to allow them to navigate to your app's top level using the system back button. For more information, see the chapter on <em>System-to-app navigation</em> in the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design pattern.</p>
+
+<h4 id="correctly_set_and_manage_notification_priority"><strong>Correctly set and manage notification priority</strong></h4>
+
+<p>Starting with Jelly Bean, Android supported a priority flag for notifications. It allows you to influence where your notification will appear in comparison to other notifications and help to make sure that users always see their most important notifications first. You can choose from the following priority levels when posting a notification:</p>
+<table>
+ <tr>
+    <td class="tab0">
+<p><strong>Priority</strong></p>
+</td>
+    <td class="tab0">
+<p><strong>Use</strong></p>
+</td>
+ </tr>
+ <tr>
+    <td class="tab1">
+<p>{@code MAX}</p>
+</td>
+    <td class="tab1">
+<p>Use for critical and urgent notifications that alert the user to a condition that is time-critical or needs to be resolved before they can continue with a particular task.</p>
+</td>
+ </tr>
+ <tr>
+    <td class="tab1">
+<p>{@code HIGH}</p>
+</td>
+    <td class="tab1">
+<p>Use high priority notifications primarily for important communication, such as message or chat events with content that is particularly interesting for the user. High priority notifications will get the Heads-Up Notification display starting in L.</p>
+</td>
+ </tr>
+ <tr>
+    <td class="tab1">
+<p>{@code DEFAULT}</p>
+</td>
+    <td class="tab1">
+<p>The default priority. Keep all notifications that don't fall into any of the other categories at this priority level.</p>
+</td>
+ </tr>
+ <tr>
+    <td class="tab1">
+<p>{@code LOW}</p>
+</td>
+    <td class="tab1">
+<p>Use for notifications that you still want the user to be informed about, but that rate low in urgency. LOW notifications will tend to show up at the bottom of the list, which makes them a good choice for things like pubic/undirected social updates: the user has asked to be notified about them, but they should never take precedence over urgent or direct communication.</p>
+</td>
+ </tr>
+ <tr>
+    <td class="tab1">
+<p>{@code MIN}</p>
+</td>
+    <td class="tab1">
+<p>Contextual/background information (e.g. weather information, contextual location information). Minimum priority notifications will not show in the status bar. The user will only discover them when they expand the notification shade.</p>
+</td>
+ </tr>
+</table>
+
+
+<h4 id="how_to_choose_an_appropriate_priority"><strong>How to choose an appropriate priority</strong></h4>
+
+<p>Default, High, and Max priority are interruptive priority levels and risk interrupting the user from what they are doing. This should not not be taken lightly, so these levels should be  reserved for notifications that:</p>
+
+<ul>
+  <li> Involve another person
+  <li> Are time-sensitive
+  <li> Might immediately change the user's behavior in the real world
+</ul>
+
+<p>Notifications set to Low and Min can still be very valuable for the user. Many if not most notifications just don't need to command the user's immediate attention, or vibrate the user's wrist, yet contain information that they will find valuable when they choose to look for notifications. Criteria for Low and Min priority notifications:</p>
+
+<ul>
+  <li> Don't involve other people
+  <li> Aren't time sensitive
+  <li> Is content the user might be interested in but could choose to browse at their leisure
+</ul>
+
+<div class="figure" style="width:624px">
+  <img src="{@docRoot}preview/images/notifications/notifications_pattern_priority.png"
+    alt="" width="624" height="210" id="figure11">
+</div>
+
+<h4 id="set_a_notification_category"><strong>Set a notification category</strong></h4>
+
+<p>If your notification falls into one of the predefined categories (see below), assign it accordingly.  Aspects of the system UI such as the notification shade (or any other notification listener) may use this information to make ranking and filtering decisions.</p>
+<table>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_CALL}</p>
+</td>
+    <td>
+<p>Incoming call (voice or video) or similar synchronous communication request</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_MESSAGE}</p>
+</td>
+    <td>
+<p>Incoming direct message (SMS, instant message, etc.)</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_EMAIL}</p>
+</td>
+    <td>
+<p>Asynchronous bulk message (email)</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_EVENT}</p>
+</td>
+    <td>
+<p>Calendar event</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_PROMO}</p>
+</td>
+    <td>
+<p>Promotion or advertisement</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_ALARM}</p>
+</td>
+    <td>
+<p>Alarm or timer</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_PROGRESS}</p>
+</td>
+    <td>
+<p>Progress of a long-running background operation</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_SOCIAL}</p>
+</td>
+    <td>
+<p>Social network or sharing update</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_ERROR}</p>
+</td>
+    <td>
+<p>Error in background operation or authentication status</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_TRANSPORT}</p>
+</td>
+    <td>
+<p>Media transport control for playback</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_SYSTEM}</p>
+</td>
+    <td>
+<p>System or device status update.  Reserved for system use.</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_SERVICE}</p>
+</td>
+    <td>
+<p>Indication of running background service</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_RECOMMENDATION}</p>
+</td>
+    <td>
+<p>A specific, timely recommendation for a single thing.  For example, a news app might want to recommend a news story it believes the user will want to read next.</p>
+</td>
+ </tr>
+ <tr>
+    <td>
+<p>{@code Notification.CATEGORY_STATUS}</p>
+</td>
+    <td>
+<p>Ongoing information about device or contextual status</p>
+</td>
+ </tr>
+</table>
+
+
+<p> </p>
+
+<h4 id="summarize_your_notifications"><strong>Summarize your notifications</strong></h4>
+
+<p>If your app creates a notification while another of the same type is still pending, avoid creating an altogether new notification object. Instead, turn it into a summary notification for the app.</p>
+
+<p>A summary notification builds a summary description and allows the user to understand how many notifications of a particular kind are pending.</p>
+
+<p><strong>Don't</strong>:</p>
+
+<div class="figure" style="width:325px">
+  <img src="{@docRoot}preview/images/notifications/Summarise_Dont.png"
+    alt="" width="325" height="361" id="figure12" />
+</div>
+
+<p><strong>Do</strong>:</p>
+
+<div class="figure" style="width:318px">
+  <img src="{@docRoot}preview/images/notifications/Summarise_Do.png"
+    alt="" width="318" height="293" id="figure13" />
+</div>
+
+<p>You can provide more detail about the individual notifications that make up a  summary by using the expanded digest layout. This allows users to gain a better sense of which notifications are pending and if they are interesting enough to be read in detail within the associated app.</p>
+
+<div class="figure" style="width:370px">
+  <img src="{@docRoot}preview/images/notifications/ExpandedText.png"
+    alt="" width="370" height="309" id="figure14" />
+  <p class="img-caption">
+    <strong>Figure 8.</strong> Expanded and contracted notification that is a summary (using InboxStyle)
+  </p>
+</div>
+
+<h4 id="make_notifications_optional"><strong>Make notifications optional</strong></h4>
+
+<p>Users should always be in control of notifications. Allow the user to disable your app's notifications or change their alert properties, such as alert sound and whether to use vibration, by adding a notification settings item to your application settings.</p>
+
+<h4 id="use_distinct_icons"><strong>Use distinct icons</strong></h4>
+
+<p>By glancing at the notification area, the user should be able to discern what kinds of notifications are currently pending.</p>
+
+<p><strong>Do</strong></p>
+
+<p>Look at the notification icons Android apps already provide and create notification icons for your app that are sufficiently distinct in appearance.</p>
+
+<p>[asset: include some sample visuals of notification icons]</p>
+
+<div class="figure" style="width:405px">
+  <img src="{@docRoot}preview/images/notifications/figure15.png"
+    alt="" width="405" height="80" id="figure15" />
+</div>
+
+<p><strong>Do</strong></p>
+
+<p>Use the proper <a href="{@docRoot}design/style/iconography.html#notification">notification icon style</a> for small icons, and the Material Light <a href="{@docRoot}design/style/iconography.html#action-bar">action bar icon style</a> for your action icons. Do not place any additional alpha (dimming or fading) into your small icons and action icons; they can have anti-aliased edges, but because L uses these icons as masks (that is, only the alpha channel is used), the image should generally be drawn at full opacity.</p>
+
+<p>[asset: show a zoomed example of how this should look]</p>
+
+<div class="figure" style="width:348px">
+  <img src="{@docRoot}preview/images/notifications/figure16.png"
+    alt="" width="348" height="300" id="figure16" />
+</div>
+
+<p><strong>Do</strong></p>
+
+<p>Keep your icons visually simple and avoid excessive detail that is hard to discern.</p>
+
+<p><strong>Don't</strong></p>
+
+<p>Use color to distinguish your app from others. Notification icons should only be a white-on-transparent background image.</p>
+
+<h4 id=pulse_the_notification_led_appropriately><strong>Pulse the notification LED appropriately</strong></h4>
+
+<p>Many Android devices contain a notification LED, which is used to keep the user informed about events while the screen is off. Notifications with a priority level of MAX, HIGH, or DEFAULT should cause the LED to glow, while those with lower priority (LOW and MIN) should not.</p>
+
+<p>The user's control over notifications should extend to the LED. When you use DEFAULT_LIGHTS, the LED will glow with a white color. Your notifications shouldn't use a different color unless the user has explicitly customized it.</p>
+
+<h2 id=building_notifications_that_users_care_about>Building notifications that users care about</h2>
+
+<p>To create an app that users love, it is important to design your notifications carefully.  Notifications embody your app's voice, and contribute to your app's personality. Unwanted or unimportant notifications can annoy the user or make them resent how much attention the app wants from them, so use notifications judiciously.</p>
+
+<h4 id=when_to_display_a_notification><strong>When to display a notification</strong></h4>
+
+<p>To create an application that people enjoy using, it's important to recognize that the user's attention and focus is a resource that must be protected. While Android's notification system has been designed to minimize the impact of notifications on the user's attention, it is nonetheless still important to be aware of the fact that notifications are interrupting the user's task flow. As you plan your notifications, ask yourself if they are important enough to warrant an interruption. If you are unsure, allow the user to opt into a notification using your apps notification settings or adjust the notifications priority flag to Low or Min to avoid distracting the user while they are doing something else.</p>
+
+<p>While well behaved apps generally only speak when spoken to, there are some limited cases where an app actually should interrupt the user with an unprompted notification.</p>
+
+<p>Notifications should be used primarily for <strong>time sensitive events</strong>, and especially if these synchronous events <strong>involve other people</strong>. For instance, an incoming chat is a real time and synchronous form of communication: there is another user actively waiting on you to respond. Calendar events are another good example of when to use a notification and grab the user's attention, because the event is imminent, and calendar events often involve other people.</p>
+
+<div class="figure" style="width:624px">
+  <img src="{@docRoot}preview/images/notifications/figure17.png"
+    alt="" width="624" height="232" id="figure17" />
+  <p class="img-caption">
+    <strong>Figure 8.</strong> Time sensitive notification examples
+  </p>
+</div>
+
+<p> </p>
+
+<h4 id=when_not_to_display_a_notification><strong>When not to display a notification</strong></h4>
+
+<p>There are however many other cases where notifications should not be used:</p>
+
+<ul>
+  <li> Avoid notifying the user of information that is not directed specifically at them, or information that is not truly time sensitive. For instance the asynchronous and undirected updates flowing through a social network generally do not warrant a real time interruption. For the users that do care about them, allow them to opt-in.
+  <li> Don't create a notification if the relevant new information is currently on screen. Instead, use the UI of the application itself to notify the user of new information directly in context. For instance, a chat application should not create system notifications while the user is actively chatting with another user.
+  <li> Don't interrupt the user for low level technical operations, like saving or syncing information, or updating an application, if it is possible for the system to simply take care of itself without involving the user.
+  <li> Don't interrupt the user to inform them of an error if it is possible for the application to recover from the error on its own without the user taking any action.
+  <li> Don't create notifications that have no true notification content and merely  advertise your app. A notification should provide useful, timely, new information and should not be used to merely launch an app.
+  <li> Don't create superfluous notifications just to get your brand in front of users. Such notifications will only frustrate and likely alienate your audience. The best way to provide the user with a small amount of updated information and to keep them engaged with your application is to develop a widget that they can choose to place on their home screen.
+</ul>
+
+<div class="figure" style="width:373px">
+  <img src="{@docRoot}preview/images/notifications/figure18.png"
+    alt="" width="373" height="734" id="figure18" />
+  <p class="img-caption">
+    <strong>Figure 9.</strong> Anti-examples of notifications
+  </p>
+</div>
+
+<h2 id=interacting_with_notifications>Interacting With Notifications</h2>
+
+<div class="figure" style="width:444px">
+  <img src="{@docRoot}preview/images/notifications/AntiSample1.png"
+    alt="" width="444" height="188" id="figure19" />
+</div>
+
+<p>Notifications are indicated by icons in the status bar and can be accessed by opening the notification drawer.</p>
+
+<p>Touching a notification opens the associated app to detailed content matching the notification. Swiping left or right on a notification removes it from the list.</p>
+
+<h4 id=ongoing_notifications><strong>Ongoing notifications</strong></h4>
+
+<p>Ongoing notifications keep users informed about an ongoing process in the background. For example, music players announce the currently playing track in the notification system and continue to do so until the user stops the playback. They can also be used to show the user feedback for longer tasks like downloading a file, or encoding a video. Ongoing notifications cannot be manually removed from the notification drawer.</p>
+
+<div class="figure" style="width:337px">
+  <img src="{@docRoot}preview/images/notifications/MusicPlayback.png"
+    alt="" width="337" height="196" id="figure20" />
+      <p class="img-caption">
+    <strong>Figure 10.</strong> Ongoing notification due to music playback
+  </p>
+</div>
+
+<p>The L lockscreen doesn't show transport controls for RCC (RemoteControlClient)s anymore. But the lockscreen <em>does</em> show notifications, so each app's playback notification is now the primary way for users to control playback from a locked state. This gives apps more control over which buttons to show and in what way, while providing a consistent experience for the user whether on the lockscreen or unlocked.</p>
+
+<h4 id=dialogs_and_toasts_are_for_feedback_not_notification><strong>Dialogs and toasts are for feedback not notification</strong></h4>
+
+<p>Your app should not create a dialog or toast if it is not currently on screen. Dialogs and Toasts should only be displayed as the immediate response to the user taking an action inside of your app. For further guidance on the use of dialogs and toasts, refer to <a href="{@docRoot}design/patterns/confirming-acknowledging.html">Confirming & Acknowledging</a>.</p>
+
+<p><strong>Ranking and ordering</strong></p>
+
+<p>Notifications are "news" and so they are essentially shown in reverse-chronological order, with special consideration given to the app's stated notification priority.</p>
+
+<p>In L, notifications are now a key part of the lockscreen, and are featured prominently every time the device display comes on. Because space on the lockscreen is tight, it is more important than ever to identify the most urgent or relevant notifications.</p>
+
+<p>Therefore, L has a more sophisticated sorting algorithm for notifications, taking into account:</p>
+
+<ul>
+  <li> The timestamp and application's stated priority, as before.
+  <li> Whether the notification has recently disturbed the user with sound or vibration. (That is, if the phone just made noise, and the user wants to know "what just happened?" the lockscreen should answer that at a glance.)
+  <li> Any people that are attached to the notification using {@code EXTRA_PEOPLE}, and in particular whether those are starred contacts.
+</ul>
+
+<p>To best take advantage of this sorting, developers should focus on the user experience they want to create rather than aiming for any particular spot on the list.</p>
+
+<p>An example:</p>
+
+<div class="figure" style="width:624px">
+  <img src="{@docRoot}preview/images/notifications/AntiSample3.png"
+    alt="" width="624" height="334" id="figure21" />
+      <p class="img-caption">
+    <strong>Figure 11.</strong> Gmail notifications are default priority, so they normally sort below messages from an instant messaging app like Hangouts, but Gmail will get a temporary bump when new messages come in.
+  </p>
+</div>
+
+<p>Give the user choices: about whether to have notifications at all, whether they should vibrate or make sound.</p>
+
+<p><strong>On the lockscreen</strong></p>
+
+<p>Starting in L, notifications are visible on the lockscreen, and so we must consider the user's privacy. Notifications often contain sensitive information, and we must take care when showing it to anyone who picks up the device and turns on the display.</p>
+
+<ul>
+  <li> For devices without a secure lockscreen, a simple slide gesture unlocks the whole device. Therefore, Android will always show the complete contents of all notifications on insecure lockscreens.
+  <li> When a device has a secure lockscreen (PIN, pattern, or password), however, it divides the interface into two spheres: "public", the things that are displayed atop a secure lockscreen and can therefore be seen by anyone; and "private", the world behind that lockscreen, which can only be accessed by supplying the correct authentication.
+</ul>
+
+<div class="figure" style="width:249px">
+  <img src="{@docRoot}preview/images/notifications/LockScreen.png"
+    alt="" width="249" height="482" id="figure22" />
+      <p class="img-caption">
+    <strong>Figure 12.</strong> Notifications on the lockscreen followed by the Pattern Unlock when the user attempts to unlock the phone.
+  </p>
+</div>
+
+<p><strong>The user decides what shows on the secure lockscreen</strong></p>
+
+<p>When setting up a secure lockscreen, the user can choose to conceal sensitive details from atop the secure lockscreen. In this case the SystemUI considers the notification's <em>visibility level</em> to figure out what can safely be shown.</p>
+
+<p>To control the visibility level, call {@code android.app.Notification.Builder.setVisibility()} and specify one of these values:</p>
+
+<ul>
+  <li>{@code android.app.Notification.VISIBILITY_PUBLIC}. Shows the notification's full content. This is the system default if visibility is left unspecified.
+  <li>{@code android.app.Notification.VISIBILITY_PRIVATE}. The lockscreen will reveal basic information about the existence of this notification, including its icon and the name of the app that posted it. The rest of the notification's details, however, are not displayed.
+  <ul>
+    <li> If you want to provide a different public version of your notification for the system to display on a secure lockscreen, supply a replacement Notification object in the {@code android.app.Notification.publicVersion} field.
+    <li> This is an app's opportunity to create a redacted version of the content that is still useful but does not reveal personal information.
+    <li> <strong>Example: </strong>An SMS app whose notifications include the text of the SMS and the sender's name and contact icon. This notification should be {@code VISIBILITY_PRIVATE}, but the {@code publicVersion} could still contain useful information like "3 new messages" without any other identifying details.
+  </ul>
+  <li>{@code android.app.Notification.VISIBILITY_SECRET}. Shows only the most minimal information, excluding even the notification's icon.
+</ul>
+
diff --git a/docs/html/preview/preview_toc.cs b/docs/html/preview/preview_toc.cs
index a292146..a505905 100644
--- a/docs/html/preview/preview_toc.cs
+++ b/docs/html/preview/preview_toc.cs
@@ -24,6 +24,12 @@
   </li>
 
   <li class="nav-section">
+    <div class="nav-section-header empty">
+    <a href="<?cs var:toroot ?>preview/notifications.html">Notification Design</a></div>
+  </li>
+
+
+  <li class="nav-section">
     <div class="nav-section-header">
       <a href="<?cs var:toroot ?>preview/tv/index.html">TV</a>
       </div>
@@ -93,9 +99,9 @@
       <a href="<?cs var:toroot ?>preview/license.html">License Agreement</a>
       </div>
   </li>
-  <li class="nav-section" style="margin: 20px 0 0 3px;">
-    <div class="nav-section-header paging-links empty">
-      <a href="<?cs var:toroot ?>index.html" class="prev-page-link">Developer Home</a>
+  <li class="nav-section" style="margin: 20px 0 0 -10px;">
+    <div class="nav-section-header empty">
+      <a href="<?cs var:toroot ?>index.html" class="back-link">Developer Home</a>
       </div>
   </li>
 </ul>
diff --git a/docs/html/preview/samples.jd b/docs/html/preview/samples.jd
index 635f49e..155ae21 100644
--- a/docs/html/preview/samples.jd
+++ b/docs/html/preview/samples.jd
@@ -3,31 +3,8 @@
 @jd:body
 
 <p>The following code samples are provided for the L Developer Preview. You can
-download them with the Android SDK Manager.</p>
-
-<p>To import a downloaded project:<p>
-
-<div class="toggle-content closed">
-<p style="margin-top:5px"><a href="#" onclick="return toggleContent(this)">
-  <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt=""
-  />Using Android Studio</a></p>
-
-  <div class="toggle-content-toggleme">
-
-  <ol>
-    <li>Unpack the downloaded project package.</li>
-    <li>In <a href="{@docRoot}sdk/installing/studio.html">Android Studio</a>, chose
-    <strong>File > Import Project</strong> and select the root folder of
-    the unpacked project.
-      <p>Android Studio may ask you to choose the type of project you are
-        importing. If it does, make sure to choose <strong>Import project from
-        external model</strong> and select the <strong>Gradle</strong> option.
-      </p>
-    </li>
-  </ol>
-
-  </div>
-</div>
+download them in the Android SDK Manager under the <b>SDK Samples</b> component
+for the L Developer Preview.</p>
 
 <p class="note">
   <strong>Note:</strong> At this time, the downloadable projects are designed
@@ -35,12 +12,10 @@
 </p>
 
 
-
-
 <h3 id="BasicManagedProfile">BasicManagedProfile</h3>
 <div class="figure" style="width:220px">
   <img src="{@docRoot}preview/images/BasicManagedProfile.png"
-     srcset="{@docRoot}preview/images/hun-BasicManagedProfile@2x.png 2x"
+     srcset="{@docRoot}preview/images/BasicManagedProfile@2x.png 2x"
      alt="" height="375" />
   <p class="img-caption">
     <strong>Figure 1.</strong> The BasicManagedProfile sample app.
@@ -58,6 +33,8 @@
 <p class="note"><strong>Note:</strong> There can be only one managed profile on
   a device at a time.</p>
 
+<p><a href="http://github.com/googlesamples/android-BasicManagedProfile">Get it on GitHub</a></p>
+
 <h3 id="Camera2Basic">Camera2Basic</h3>
 
 <!--
@@ -72,6 +49,7 @@
 <p>This sample demonstrates the basic use of the Camera2 API. The sample code
 demonstrates how you can display camera preview and take pictures.</p>
 
+<p><a href="http://github.com/googlesamples/android-Camera2Basic">Get it on GitHub</a></p>
 
 
 <h3 id="Camera2Video">Camera2Video</h3>
@@ -83,8 +61,10 @@
   </p>
 </div>
 -->
+
 <p>This sample demonstrates how to record video using the Camera2 API.</p>
 
+<p><a href="http://github.com/googlesamples/android-Camera2Video">Get it on GitHub</a></p>
 
 <h3 id="ActivitySceneTransitionBasic">ActivitySceneTransitionBasic</h3>
 <div class="figure" style="width:220px">
@@ -101,6 +81,7 @@
 of <code>moveImage</code> and <code>changeBounds</code> to nicely transition
 from a grid of images to an activity with a large image and detail text. </p>
 
+<p><a href="http://github.com/googlesamples/android-ActivitySceneTransition">Get it on GitHub</a></p>
 
 <h3 id="ElevationBasic">ElevationBasic</h3>
 <!--
@@ -111,6 +92,7 @@
   </p>
 </div>
 -->
+
 <p>
 This sample demonstrates two alternative ways to move a view in the z-axis:</p>
 
@@ -120,7 +102,7 @@
       <code>setTranslationZ()</code>.</li>
 </ul>
 
-
+<p><a href="http://github.com/googlesamples/android-ElevationBasic">Get it on GitHub</a></p>
 
 <h3 id="ElevationDrag">ElevationDrag</h3>
 <!--
@@ -136,6 +118,7 @@
 Elevation and z-translation are used to render the shadows. The views are
 clipped using different outlines.</p>
 
+<p><a href="http://github.com/googlesamples/android-ElevationDrag">Get it on GitHub</a></p>
 
 
 <h3 id="ClippingBasic">ClippingBasic</h3>
@@ -147,11 +130,21 @@
   </p>
 </div>
 -->
+
 <p>
 This sample demonstrates clipping on a {@link android.view.View}.
 </p>
 
+<p><a href="http://github.com/googlesamples/android-ClippingBasic">Get it on GitHub</a></p>
 
+<div class="figure" style="width:220px">
+  <img src="{@docRoot}preview/images/JobSchedulerSample.png"
+      srcset="{@docRoot}preview/images/JobSchedulerSample@2x.png 2x"
+      alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure 3.</strong> The JobSchedulerSample sample app.
+  </p>
+</div>
 
 <h3 id="GameControllerSample">GameControllerSample</h3>
 <!--
@@ -162,11 +155,13 @@
   </p>
 </div>
 -->
+
 <p>
 This sample implements a multi-player game, demonstrating game controller input
 handling.
 </p>
 
+<p><a href="http://github.com/googlesamples/androidtv-GameController">Get it on GitHub</a></p>
 
 
 <h3 id="Visual-Game-Controller">Visual-Game-Controller</h3>
@@ -178,11 +173,12 @@
   </p>
 </div>
 -->
+
 <p>
 This sample displays events received from a game controller shown on the screen.
 </p>
 
-
+<p><a href="http://github.com/googlesamples/androidtv-VisualGameController">Get it on GitHub</a></p>
 
 <h3 id="AndroidTVLeanbackSample">AndroidTVLeanbackSample</h3>
 <!--
@@ -193,29 +189,21 @@
   </p>
 </div>
 -->
+
 <p>
 This sample demonstrates use of the Android TV Leanback Support Library.
 </p>
 
-
+<p><a href="http://github.com/googlesamples/androidtv-Leanback">Get it on GitHub</a></p>
 
 <h3 id="JobSchedulerSample">JobSchedulerSample</h3>
 
-<div class="figure" style="width:220px">
-  <img src="{@docRoot}preview/images/JobSchedulerSample.png"
-      srcset="{@docRoot}preview/images/JobSchedulerSample@2x.png 2x"
-      alt="" height="375" />
-  <p class="img-caption">
-    <strong>Figure 3.</strong> The JobSchedulerSample sample app.
-  </p>
-</div>
-
 <p>
 This sample app allows the user to schedule jobs through the UI, and shows
 visual cues when the jobs are executed.
 </p>
 
-
+<p><a href="http://github.com/googlesamples/android-JobScheduler">Get it on GitHub</a></p>
 
 <h3 id="NavigationDrawerSample">NavigationDrawerSample</h3>
 <!--
@@ -226,12 +214,13 @@
   </p>
 </div>
 -->
+
 <p>
 This sample illustrates a common usage of the Android support library's
 {@link android.support.v4.widget.DrawerLayout} widget.
 </p>
 
-
+<p><a href="http://github.com/googlesamples/android-NavigationDrawer">Get it on GitHub</a></p>
 <!--
 <h3 id="">SampleName</h3>
 
diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd
index 876b348..af466ab 100644
--- a/docs/html/preview/setup-sdk.jd
+++ b/docs/html/preview/setup-sdk.jd
@@ -1,6 +1,174 @@
 page.title=Setting Up the Preview SDK
 @jd:body
 
+
+
+
+
+
+
+<div style="position:relative; min-height:600px">
+
+  <div class="wrap" id="tos" style="position:absolute;display:none;width:inherit;">
+
+    <p class="sdk-terms-intro">Before installing the Android SDK, you must agree to the following terms and conditions.</p>
+
+      <h2 class="norule">Terms and Conditions</h2>
+    <div class="sdk-terms" onfocus="this.blur()" style="width:678px">
+This is the Android SDK Preview License Agreement (the “License Agreement”).
+
+1. Introduction
+
+1.1 The Android SDK Preview (referred to in the License Agreement as the “Preview” and specifically including the Android system files, packaged APIs, and Preview library files, if and when they are made available) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the Preview.
+
+1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
+
+1.3 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
+
+2. Accepting the License Agreement
+
+2.1 In order to use the Preview, you must first agree to the License Agreement. You may not use the Preview if you do not accept the License Agreement.
+
+2.2 By clicking to accept and/or using the Preview, you hereby agree to the terms of the License Agreement.
+
+2.3 You may not use the Preview and may not accept the License Agreement if you are a person barred from receiving the Preview under the laws of the United States or other countries including the country in which you are resident or from which you use the Preview.
+
+2.4 If you will use the Preview internally within your company or organization you agree to be bound by the License Agreement on behalf of your employer or other entity, and you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the Preview on behalf of your employer or other entity.
+
+3. Preview License from Google
+
+3.1 Subject to the terms of the License Agreement, Google grants you a royalty-free, non-assignable, non-exclusive, non-sublicensable, limited, revocable license to use the Preview, personally or internally within your company or organization, solely to develop applications to run on the Android platform.
+
+3.2 You agree that Google or third parties owns all legal right, title and interest in and to the Preview, including any Intellectual Property Rights that subsist in the Preview. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
+
+3.3 You may not use the Preview for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the Preview or any part of the Preview; or (b) load any part of the Preview onto a mobile handset or any other hardware device except a personal computer, combine any part of the Preview with other software, or distribute any software or device incorporating a part of the Preview.
+
+3.4 You agree that you will not take any actions that may cause or result in the fragmentation of Android, including but not limited to distributing, participating in the creation of, or promoting in any way a software development kit derived from the Preview.
+
+3.5 Use, reproduction and distribution of components of the Preview licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement. You agree to remain a licensee in good standing in regard to such open source software licenses under all the rights granted and to refrain from any actions that may terminate, suspend, or breach such rights.
+
+3.6 You agree that the form and nature of the Preview that Google provides may change without prior notice to you and that future versions of the Preview may be incompatible with applications developed on previous versions of the Preview. You agree that Google may stop (permanently or temporarily) providing the Preview (or any features within the Preview) to you or to users generally at Google's sole discretion, without prior notice to you.
+
+3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
+
+3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the Preview.
+
+4. Use of the Preview by You
+
+4.1 Google agrees that nothing in the License Agreement gives Google any right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the Preview, including any intellectual property rights that subsist in those applications.
+
+4.2 You agree to use the Preview and write applications only for purposes that are permitted by (a) the License Agreement, and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
+
+4.3 You agree that if you use the Preview to develop applications, you will protect the privacy and legal rights of users. If users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If users provide you with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, each user has given you permission to do so.
+
+4.4 You agree that you will not engage in any activity with the Preview, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of Google or any third party.
+
+4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
+
+4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
+
+4.7 The Preview is in development, and your testing and feedback are an important part of the development process. By using the Preview, you acknowledge that implementation of some features are still under development and that you should not rely on the Preview having the full functionality of a stable release. You agree not to publicly distribute or ship any application using this Preview as this Preview will no longer be supported after the official Android SDK is released.
+
+5. Your Developer Credentials
+
+5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
+
+6. Privacy and Information
+
+6.1 In order to continually innovate and improve the Preview, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the Preview are being used and how they are being used. Before any of this information is collected, the Preview will notify you and seek your consent. If you withhold consent, the information will not be collected.
+
+6.2 The data collected is examined in the aggregate to improve the Preview and is maintained in accordance with Google's Privacy Policy located at http://www.google.com/policies/privacy/.
+
+7. Third Party Applications
+
+7.1 If you use the Preview to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
+
+7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
+
+7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party.
+
+8. Using Google APIs
+
+8.1 Google APIs
+
+8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
+
+8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
+
+9. Terminating the License Agreement
+
+9.1 the License Agreement will continue to apply until terminated by either you or Google as set out below.
+
+9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the Preview and any relevant developer credentials.
+
+9.3 Google may at any time, terminate the License Agreement, with or without cause, upon notice to you.
+
+9.4 The License Agreement will automatically terminate without notice or other action upon the earlier of:
+(A) when Google ceases to provide the Preview or certain parts of the Preview to users in the country in which you are resident or from which you use the service; and
+(B) Google issues a final release version of the Android SDK.
+
+9.5 When the License Agreement is terminated, the license granted to you in the License Agreement will terminate, you will immediately cease all use of the Preview, and the provisions of paragraphs 10, 11, 12 and 14 shall survive indefinitely.
+
+10. DISCLAIMERS
+
+10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE PREVIEW IS AT YOUR SOLE RISK AND THAT THE PREVIEW IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
+
+10.2 YOUR USE OF THE PREVIEW AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE PREVIEW IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. WITHOUT LIMITING THE FOREGOING, YOU UNDERSTAND THAT THE PREVIEW IS NOT A STABLE RELEASE AND MAY CONTAIN ERRORS, DEFECTS AND SECURITY VULNERABILITIES THAT CAN RESULT IN SIGNIFICANT DAMAGE, INCLUDING THE COMPLETE, IRRECOVERABLE LOSS OF USE OF YOUR COMPUTER SYSTEM OR OTHER DEVICE.
+
+10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+
+11. LIMITATION OF LIABILITY
+
+11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
+
+12. Indemnification
+
+12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys’ fees) arising out of or accruing from (a) your use of the Preview, (b) any application you develop on the Preview that infringes any Intellectual Property Rights of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you of the License Agreement.
+
+13. Changes to the License Agreement
+
+13.1 Google may make changes to the License Agreement as it distributes new versions of the Preview. When these changes are made, Google will make a new version of the License Agreement available on the website where the Preview is made available.
+
+14. General Legal Terms
+
+14.1 the License Agreement constitutes the whole legal agreement between you and Google and governs your use of the Preview (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the Preview.
+
+14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
+
+14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
+
+14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
+
+14.5 EXPORT RESTRICTIONS. THE PREVIEW IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE PREVIEW. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
+
+14.6 The License Agreement may not be assigned or transferred by you without the prior written approval of Google, and any attempted assignment without such approval will be void. You shall not delegate your responsibilities or obligations under the License Agreement without the prior written approval of Google.
+
+14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
+    </div><!-- sdk terms -->
+
+
+
+    <div id="sdk-terms-form">
+      <p>
+        <input id="agree" type="checkbox" name="agree" value="1" onclick="onAgreeChecked()" />
+        <label id="agreeLabel" for="agree">I have read and agree with the above terms and conditions</label>
+      </p>
+      <p><a href="" class="button disabled" id="downloadForRealz" onclick="return onDownloadForRealz(this);"></a></p>
+    </div>
+
+
+  </div><!-- end TOS -->
+
+
+
+
+
+
+
+
+
+  <div id="landing">
+
 <p>The Preview SDK is available from the Android SDK Manager. <!-- Not yet! -->
 This document assumes that you are familiar with Android app development, such
 as using the Android SDK Manager and creating projects. If you're new to
@@ -52,26 +220,25 @@
 
 <ol>
   <li>Download and uncompress the Android Developer Preview package.
-    <p class="table-caption" id="table1">
-      <strong>Table 1.</strong> L Developer Preview system images.</p>
-    <table>
+    <table style="width:860px">
       <tr>
         <th scope="col">Device</th>
         <th scope="col">Download</th>
-        <th scope="col">MD5 Checksum</th>
-        <th scope="col">SHA-1 Checksum</th>
+        <th scope="col">Checksum</th>
       </tr>
       <tr id="hammerhead">
-        <td>Nexus 5 (GSM/LTE) "hammerhead"</td>
-        <td><!-- TODO --></td>
-        <td><code>5a6ae77217978cb7b958a240c2e80b57</code></td>
-        <td><code>ac1d8a8e4f4a1dca5864dc733caa940bffc28616</code></td>
+        <td>Nexus 5 (GSM/LTE) <br>"hammerhead"</td>
+        <td><a href="#top" onclick="onDownload(this)"
+          >hammerhead-lpv79-preview-ac1d8a8e.tgz</a></td>
+        <td>MD5: <code>5a6ae77217978cb7b958a240c2e80b57</code>
+        <br>SHA-1: <code>ac1d8a8e4f4a1dca5864dc733caa940bffc28616</code></td>
       </tr>
       <tr id="razor">
-        <td>Nexus 7 (Wifi) "razor"</td>
-        <td><!-- TODO --></td>
-        <td><code>b293a5d3a4e07beabebcc0be85ad68a2</code></td>
-        <td><code>d0ddf8ce733ba2a34279cdff8827fd604762c2342d</code></td>
+        <td>Nexus 7 (Wifi) <br>"razor"</td>
+        <td><a href="#top" onclick="onDownload(this)"
+          >razor-lpv79-preview-d0ddf8ce.tgz</a></td>
+        <td>MD5: <code>b293a5d3a4e07beabebcc0be85ad68a2</code>
+        <br><nobr>SHA-1: <code>d0ddf8ce733ba2a34279cdff8827fd604762c2342d</nobr></td>
       </tr>
     </table>
   </li>
@@ -142,3 +309,56 @@
     &lt;/style>
 &lt;/resources>
 </pre>
+
+  </div><!-- landing -->
+
+</div><!-- relative wrapper -->
+
+
+
+<script>
+  var urlRoot = "http://storage.googleapis.com/androiddevelopers/preview/";
+  function onDownload(link) {
+
+    $("#downloadForRealz").html("Download " + $(link).text());
+    $("#downloadForRealz").attr('href', urlRoot + $(link).text());
+
+    $("#tos").fadeIn('fast');
+    $("#landing").fadeOut('fast');
+
+    return true;
+  }
+
+
+  function onAgreeChecked() {
+    /* verify that the TOS is agreed */
+    if ($("input#agree").is(":checked")) {
+      /* reveal the download button */
+      $("a#downloadForRealz").removeClass('disabled');
+    } else {
+      $("a#downloadForRealz").addClass('disabled');
+    }
+  }
+
+  function onDownloadForRealz(link) {
+    if ($("input#agree").is(':checked')) {
+      $("#tos").fadeOut('fast');
+      $("#landing").fadeIn('fast');
+      _gaq.push(['_trackEvent', 'L Preview', 'System Image', $("#downloadForRealz").html()]);
+      location.hash = "";
+      return true;
+    } else {
+      $("label#agreeLabel").parent().stop().animate({color: "#258AAF"}, 200,
+        function() {$("label#agreeLabel").parent().stop().animate({color: "#222"}, 200)}
+      );
+      return false;
+    }
+  }
+
+  $(window).hashchange( function(){
+    if (location.hash == "") {
+      location.reload();
+    }
+  });
+
+</script>
\ No newline at end of file
diff --git a/docs/html/preview/tv/games/index.jd b/docs/html/preview/tv/games/index.jd
index b9de3a4..763eada 100644
--- a/docs/html/preview/tv/games/index.jd
+++ b/docs/html/preview/tv/games/index.jd
@@ -1,70 +1,152 @@
-page.title=Games on TV
+ikpage.title=Games on TV
 page.tags="controller"
 
 @jd:body
 
-<p>This section complements the [larger best-practices guidance for designing for Android TV](TODO, use formal name of referenced doc, and add link). It assumes that you have read that guidance, and seeks to minimize repetition.</p>
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#display">Display</li></a></li>
+    <li><a href="#control">Input Devices</li></a></li>
+    <li><a href="#manifest">Manifest</li></a></li>
+    <li><a href="#gpgs">Google Play Game Services</li></a></li>
+    <li><a href="#web">Web</a></li>
+  </ol>
+</div>
+</div>
 
-<h2>Overview</h2>
-<p>Because of factors including its large size, its control scheme, and its nature as a shared display, the television screen presents a number of considerations that may be new to mobile developers. This document breaks these considerations down into five sections:</p>
+<p>The television screen presents a number of considerations that may be new to mobile-game
+developers. These areas include its large size, its control scheme, and the fact that all
+players are viewing it simultaneously.</p>
+
+
+<h2 id=display>Display</h2>
+<p>The two main things to keep in mind when developing games for the TV screen are its nature as a
+shared display and the need to design your game for a landscape orientation.</p>
+<h3>Shared display</h3>
+<p>A living-room TV poses design challenges for multiplayer games, in that all players can see
+everything. This issue is especially relevant to games (such as card games or strategy games) that
+rely on each player’s possession of hidden information.</p>
+<p>Some mechanisms you can implement to address the problem of one player’s eavesdropping
+on another’s information are:</p>
 <ul>
-<li>Display</li>
-<li>Control</li>
-<li>Manifest</li>
-<li>Google Play Game Services</li>
-<li>Web</li>
+<li>A blinder on the screen to help conceal information. For example, in a
+turn-based game like a word or card game, one player at a time might view the display. When the
+player finishes a move, the game allows him or her to cover the screen with a blinder that
+blocks anyone from viewing secret information. When the next player begins a turn, the blinder
+opens to reveal his or her own information.</li>
+<li>A companion app, running on a phone or tablet, can enable a player to conceal
+information.</li>
 </ul>
-<h2>Display</h2>
-<p>Large and centrally situated, the television screen imposes limitations, but also opens up new opportunities for immersive gameplay.</p>
-<h3>A shared display</h3>
-<p>A living-room TV poses design challenges for multiplayer games, in that all players can see everything. This issue is especially germane to games (such as card games or strategy games) that rely on each player’s possession of hidden information.</p>
-<p>Some mechanisms you can implement to address the problem of one player’s “eavesdropping” on another’s information are:</p>
-<ul>
-<li>A player might place a "blinder" on the screen to help conceal information. For example, in a turn-based game like a word or card game, one player at a time might view the display. When the player finishes a move, the game allows him or her to cover the screen with a “blinder” that blocks anyone from viewing secret information. When the next player begins a turn, the blinder opens to reveal his or her own information.</li>
-<li>A second screen, such as a handset or larger device, can enable a player to conceal information. For information on implementing second-screen support, see <a href="http://developer.android.com/reference/android/app/Presentation.html">Presentation</a> on the Android developer site.</li>
-</ul>
-<h3>No touch interface</h3>
-<p>A television does not have a touch interface. Your game design, therefore, need not take into account the possibility that a player’s controlling fingers might block the on-screen action. You can assume constant visibility of the entire viewing area.</p>
-<p>See the <a href=#control>Control</a> section in this document and in [Design for TV](TODO, use formal name of referenced doc, and add link) for more implications of the lack of touch interface.</p>
 <h3>Landscape display</h3>
-<p>In mobile-device terms, a TV is always “sideways.” You can’t turn it, and there is no portrait orientation. You should always be designing your TV games to be displayed in landscape mode.</p>
-<a id=control><h2>Control</h2>
-<p>Without a touch interface, it's even more important than usual to get your controls right, so that players find them intuitive and fun to use. The separation of controller from device also introduces some other issues to pay attention to, like keeping track of multiple players' controllers, and handling disconnects gracefully.</p>
+<p>A TV is always sideways: You can’t turn it, and there is no
+portrait orientation. Always design your TV games to be displayed in landscape
+mode.</p>
+
+<h2 id="control">Input Devices</h2>
+<p>TVs don't have touch interfaces, so it's even more important to get your controls right and make
+ sure that players find them intuitive and fun to use. The separation of controller from device also
+introduces some other issues to pay attention to, like keeping track of multiple players'
+controllers, and handling disconnects gracefully.</p>
 <h3>D-pad</h3>
-<p>Because of the lack of touch interface, you should be planning your control scheme based on a D-pad. Some key points to keep in mind include:</p>
-<p>The player needs to use the gamepad in all aspects of the game&ndash;not just controlling core gameplay, but also navigating menus and ads. For this reason, you should also ensure that your Android TV game does not refer to a touch interface: for example, an Android TV game cannot tell a player to "Tap to skip".</p>
-<p>You can avoid unhappy surprises (and resulting low ratings) by using your Play Store description to communicate to the player any expectations about controllers. If a game is better suited to a gamepad with a joystick than one with only a D-pad, you should make this clear. A player who uses an ill-suited controller for a game is likely to have a subpar experience&ndash;and penalize your game in the ratings.</p>
-<p>You can also help ensure a good player experience by ensuring that button mapping is intuitive and flexible. For example, you can adhere to accepted custom by using the A button to <code>Accept</code>, and the B button to <code>Cancel</code>. You can also offer flexibility in the form of remappability. For more information on button mapping, see <a href="http://developer.android.com/training/game-controllers/controller-input.html">Handling Controller Actions</a>.</p>
-<p>Your game can also contribute to a good match between controller and game by querying the controller about its capabilities. For example, you may intend for a player to steer an object by waving the controller in the air. If a player's controller lacks accelerometer and gyroscope hardware, however, waving will not work. But when your game queries the controller and discovers that motion detection is not supported, it can switch over to an alternative, available control scheme.</p>
-<p>For more information on querying controller capabilities, see <a href="http://developer.android.com/training/game-controllers/compatibility.html">Supporting Controllers Across Android Versions</a>.</p>
+<p>Plan your control scheme around a directional pad (D-pad) control, since this control set is the
+default for Android TV devices. The player needs to be able to use a D-Pad in all aspects of the
+game&ndash;not just controlling core
+gameplay, but also navigating menus and ads. For this reason, you should also ensure that your
+Android TV game does not refer to a touch interface: for example, an Android TV game cannot tell a
+player to <strong>Tap to skip</strong>.</p>
+<p>How you shape the player's interaction with the controller can be key to achieving a great user
+experience:
+  <ul>
+  <p><li><strong>Communicate Controller Requirements up Front</strong> - Use your Play Store description to communicate to the player any expectations about
+controllers. If a game is better suited to a gamepad with a joystick than one with only a D-pad,
+make this fact clear. A player who uses an ill-suited controller for a game is likely to have a
+subpar experience&ndash;and penalize your game in the ratings.</p>
+  <p><li><strong>Use Consistent Button Mapping</strong> - Intuitive and flexible button mapping is key to a good user experience. For example,
+you can adhere to accepted custom by using the A button to <code>Accept</code>, and the B button to
+<code>Cancel</code>. You can also offer flexibility in the form of remappability. For more
+information on button mapping, see <a
+href="http://developer.android.com/training/game-controllers/controller-input.html">Handling
+Controller Actions</a>.</p>
+  <p><li><strong>Detect Controller Capabilities and Adjust Accordingly</strong> - Query the controller about its capabilities in order to optimize the match between
+controller and game. For example, you may intend for a player to steer an object by waving the
+controller in the air. If a player's controller lacks accelerometer and gyroscope hardware, however,
+waving will not work. When, however, your game queries the controller and discovers that motion detection
+is not supported, it can switch over to an alternative, available control scheme.
+For more information on querying controller capabilities, see <a
+href="http://developer.android.com/training/game-controllers/compatibility.html">Supporting
+Controllers Across Android Versions</a>.</p>
+  </ul>
 <h3>Back-button behavior</h3>
-<p>The Back button should never act as a toggle. For example, do not use it to both open and close a menu. Its behavior should only be linear. For example: Game play &gt; Game pause screen &gt; Game main screen &gt; Android home screen.</p>
-<p>With this principle of "linear navigation" in mind, you <b>may</b> use the back button to leave an in-game menu (opened by a different button) and return to gameplay.</p>
+<p>The Back button should never act as a toggle. For example, do not use it to both open and close
+a menu. It should only navigate backward, breadcrumb-style, through the previous screens the player has
+been on. For example: Game play &gt; Game pause screen &gt; Game
+main screen &gt; Android home screen.</p>
+<p>Since the Back button should only perform linear (backward) navigation, you may use the
+back button to leave an in-game menu (opened by a different button) and return to gameplay. For
+more information about design for navigation, see <a
+href="http://developer.android.com/design/patterns/navigation.html">Navigation with Back and
+Up</a>. To learn about implementation, refer to <a
+href="http://developer.android.com/training/implementing-navigation/temporal.html">Providing Proper
+Back Navigation</a>. </p>
 <h3>Handling multiple controllers</h3>
-<p>When multiple players are playing a game, each with his or her own controller, it is important to map each player-controller pair. For information on how to implement controller-number identification, see <a href="http://developer.android.com/reference/android/view/InputDevice.html#getControllerNumber(">Input Devices</a>) on the Android developer site.</p>
+<p>When multiple players are playing a game, each with his or her own controller, it is important
+to map each player-controller pair. For information on how to implement controller-number
+identification, see <a href="http://developer.android.com/reference/android/view/InputDevice.html
+#getControllerNumber(">Input Devices</a>) on the Android developer site.</p>
 <h3>Handling disconnects</h3>
-<p>When a controller is disconnected in the middle of gameplay, the game should pause, and a dialog should appear prompting the disconnected player to reconnect his or her controller.</p>
-<p>The dialog should also offer troubleshooting tips (e.g., "Check your Bluetooth connection").</p>
-<h2>Manifest</h2>
-<p>Games are displayed in a separate row from regular apps in the launcher. Android TV uses the <code>android:isGame</code> flag to differentiate games from non-game apps. You can assign it a value of either <code>true</code> or <code>false</code>. For example:</p>
+<p>When a controller is disconnected in the middle of gameplay, the game should pause, and a dialog
+should appear prompting the disconnected player to reconnect his or her controller.</p>
+<p>The dialog should also offer troubleshooting tips (for example, a pop-up dialog telling the player to
+"Check your Bluetooth connection"). For more information on implementing input-device support, see <a
+href="http://developer.android.com/training/game-controllers/controller-input.html">Supporting Game
+Controllers"</a>. Specific information about Bluetooth connections is at <a
+href="http://developer.android.com/guide/topics/connectivity/bluetooth.html">Bluetooth</a>.</p>
+
+<h2 id="manifest">Manifest</h2>
+<p>Games are displayed in a separate row from regular apps in the launcher. Android TV uses the
+<code>android:isGame</code> flag to differentiate games from non-game apps. You can assign it a
+value of either <code>true</code> or <code>false</code>. For example:</p>
 <pre class="fragment">&lt;application&gt;
- . . .
- &lt;meta-data android:name="isGame" android:value=["true" | "false"]/&gt;
-android:isGame=["true" | "false"] &gt;
- . . .
-&lt;/application&gt;
-</pre><h2>Google Play Game Services</h2>
-<p>If your game integrates Google Play Game Services, you should keep in mind a number of considerations pertaining to achievements, sign-on, saving games, and multiplayer play.</p>
+ ...
+&lt; android:isGame=["true" | "false"] &gt;
+ ...
+&lt;/application&gt;</pre>
+
+<h2 id="gpgs">Google Play Game Services</h2>
+<p>If your game integrates Google Play Game Services, you should keep in mind a number of
+considerations pertaining to achievements, sign-on, saving games, and multiplayer play.</p>
 <h3>Achievements</h3>
-<p>Your game should include at least five (earnable) achievements. Only a user controlling gameplay from a supported input device should be able to earn achievements.</p>
-<h3>Sign-on</h3>
-<p>Your game should attempt to sign the user in on launch. If the player declines sign-in several times in a row, your game should stop asking.</p>
+<p>Your game should include at least five (earnable) achievements. Only a user controlling gameplay
+from a supported input device should be able to earn achievements. For more information on
+Achievements and how to implement them, see <a
+href="https://developers.google.com/games/services/android/achievements">Achievements in
+Android</a>.</p>
+<h3>Sign-in</h3>
+<p>Your game should attempt to sign the user in on launch. If the player declines sign-in several
+times in a row, your game should stop asking. Learn more about sign-in at <a
+href="https://developers.google.com/games/services/training/signin">Implementing Sign-in on
+Android</a>.</p>
 <h3>Saving</h3>
-<p>We highly recommend using Play Services cloud save to store your game save. Your game should bind game saves to a specific Google account, so as to be uniquely identifiable even across devices: Whether the player is using a handset or a TV, the game should be able to pull the same game-save information from his or her account.</p>
-<p>You should also provide an option in your game's UI to prompt the player to destroy save data. You might put the option in the game's <code>Settings</code> screen.</p>
+<p>We highly recommend using Play Services <a
+href="https://developers.google.com/games/services/common/concepts/cloudsave">Cloud Save</a> to
+store your game save. Your game should bind game saves to a specific Google account, so as to be
+uniquely identifiable even across devices: Whether the player is using a handset or a TV, the game
+should be able to pull the same game-save information from his or her account.</p>
+<p>You should also provide an option in your game's UI to allow the player to delete locally and
+cloud-stored data. You might put the option in the game's <code>Settings</code> screen. For
+specifics on implementing Cloud Save, see <a
+href="https://developers.google.com/games/services/android/cloudsave">Cloud Save in Android</a>.</p>
 <h3>Multiplayer experience</h3>
-<p>A game offering a multiplayer experience must allow at least two players to enter a room.</p>
-<h2>Web</h2>
-<p>Android TV games do not support a full web browser. You should therefore avoid using generic URLs in your game.</p>
-<p>Webviews will work for logins to services like Google+ and Facebook. </p>
+<p>A game offering a multiplayer experience must allow at least two players to enter a room. For
+further information on multiplayer games in Android, see the <a
+href="https://developers.google.com/games/services/android/realtimeMultiplayer">Real-time
+Multiplayer</a> and <a href="">Turn-based Multiplayer</a> documentation on the Android developer
+site.</p>
+
+<h2 id="web">Web</h2>
+<p>We discourage including web browsing in games for Android TV. The television set is not well-suited for browsing,, either in terms of display or control scheme.</p>
+<p class="note"><strong>Note:</strong> You can use the {@link android.webkit.WebView} class for logins to services like Google+ and
+Facebook. </p>
 
diff --git a/docs/html/preview/tv/start/index.jd b/docs/html/preview/tv/start/index.jd
index 11d6ad3..b75fee0 100644
--- a/docs/html/preview/tv/start/index.jd
+++ b/docs/html/preview/tv/start/index.jd
@@ -153,8 +153,7 @@
 </p>
 
 <p>If you decide to use the v17 leanback library for your app, you should note that it is
-  dependent on the <a href="{@docRoot}tools/support-library/features.html#v7-appcompat">v7
-  appcompat library</a>, which is, in turn, dependent on the
+  dependent on the
   <a href="{@docRoot}tools/support-library/features.html#v4">v4 support library</a>. This means
   that apps that use the leanback support library should include all of these support
   libraries:</p>
@@ -162,12 +161,11 @@
 <ul>
   <li>v17 leanback support library</li>
   <li>v7 recyclerview support library</li>
-  <li>v7 appcompat support library</li>
   <li>v4 support library</li>
 </ul>
 
-<p>Two of these libraries (v17 leanback and v7 appcompat) contain resources, which require
-  you to take specific steps to include them in app projects. For instructions on
+<p>The v17 leanback library contain resources, which requires
+  you to take specific steps to include it in app projects. For instructions on
   importing a support library with resources, see
   <a href="http://developer.android.com/tools/support-library/setup.html#libs-with-res">
   Support Library Setup</a>.
diff --git a/docs/html/preview/tv/ui/browse.jd b/docs/html/preview/tv/ui/browse.jd
index d7a1fb6..d6b97c1 100644
--- a/docs/html/preview/tv/ui/browse.jd
+++ b/docs/html/preview/tv/ui/browse.jd
@@ -152,10 +152,9 @@
   image as users browse through content. This technique can make interaction with your app feel more
   cinematic and enjoyable for users.</p>
 
-<p>The Leanback support library provides a {@link
-  android.support.v17.leanback.app.BackgroundManager} class for changing the background of your TV
-  app activity. The following example shows how to create a simple method for updating the
-  background within your TV app activity:</p>
+<p>The Leanback support library provides a {@code BackgroundManager} class for changing the
+  background of your TV app activity. The following example shows how to create a simple method
+  for updating the background within your TV app activity:</p>
 
 <pre>
 protected void updateBackground(Drawable drawable) {
@@ -166,7 +165,7 @@
 <p>Many of the existing media-browse apps automatically update the background as the user
   navigates through media listings. In order to do this, you can set up a selection listener to
   automatically update the background based on the user's current selection. The following example
-  shows you how to set up an {@link android.support.v17.leanback.widget.OnItemSelectedListener}
+  shows you how to set up an {@code OnItemSelectedListener}
   class to catch selection events and update the background:</p>
 
 <pre>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index dc3b9dd..14a5e1d 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -4,45 +4,45 @@
 header.hide=1
 page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
 
-sdk.version=22.6.2
+sdk.version=23.0.0
 
-sdk.linux32_bundle_download=adt-bundle-linux-x86-20140321.zip
-sdk.linux32_bundle_bytes=527971926
-sdk.linux32_bundle_checksum=943ae4d28fe7c79108c8bf2aafd5e6d2
+sdk.linux32_bundle_download=adt-bundle-linux-x86-20140624.zip
+sdk.linux32_bundle_bytes=378659422
+sdk.linux32_bundle_checksum=692e6135ed459f1e8a10498363f19f67
 
-sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20140321.zip
-sdk.linux64_bundle_bytes=528187678
-sdk.linux64_bundle_checksum=f2a2153b5c7dbaeb86b550bf4f770c36
+sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20140624.zip
+sdk.linux64_bundle_bytes=378966059
+sdk.linux64_bundle_checksum=0f14b4aed1eb1feed778ad6ed76ba01c
 
-sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20140321.zip
-sdk.mac64_bundle_bytes=501955296
-sdk.mac64_bundle_checksum=4a08649cea9b098cdf7349f452294014
+sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20140624.zip
+sdk.mac64_bundle_bytes=327367424
+sdk.mac64_bundle_checksum=7d16e83263259882901f12055a8fe3f2
 
-sdk.win32_bundle_download=adt-bundle-windows-x86-20140321.zip
-sdk.win32_bundle_bytes=535085536
-sdk.win32_bundle_checksum=b61495a6bf591cc374c31bce4fc46ec0
+sdk.win32_bundle_download=adt-bundle-windows-x86-20140624.zip
+sdk.win32_bundle_bytes=377325518
+sdk.win32_bundle_checksum=5655cd8be53c4b27c5242d81943c5a25
 
-sdk.win64_bundle_download=adt-bundle-windows-x86_64-20140321.zip
-sdk.win64_bundle_bytes=535287324
-sdk.win64_bundle_checksum=a6f4699bbdc5a29b371ed60610535651
+sdk.win64_bundle_download=adt-bundle-windows-x86_64-20140624.zip
+sdk.win64_bundle_bytes=377477237
+sdk.win64_bundle_checksum=0f1fa29a0f229e36ba0fb87bb7ee68d4
 
 
 
-sdk.linux_download=android-sdk_r22.6.2-linux.tgz
-sdk.linux_bytes=101050024
-sdk.linux_checksum=ff1541418a44d894bedc5cef10622220
+sdk.linux_download=android-sdk_r23-linux.tgz
+sdk.linux_bytes=137880976
+sdk.linux_checksum=fd768c56423e398b3e4aa8895c393bf5
 
-sdk.mac_download=android-sdk_r22.6.2-macosx.zip
-sdk.mac_bytes=74639394
-sdk.mac_checksum=2a319c862dd1dcf450bfe2a6b3d9c608
+sdk.mac_download=android-sdk_r23-macosx.zip
+sdk.mac_bytes=88015023
+sdk.mac_checksum=3869e5b9de8d69f90509568686fb7ce8
 
-sdk.win_download=android-sdk_r22.6.2-windows.zip
-sdk.win_bytes=108917505
-sdk.win_checksum=6e5bfdb7b9c1d231ed6ec78b31551cbf
+sdk.win_download=android-sdk_r23-windows.zip
+sdk.win_bytes=138459944
+sdk.win_checksum=9daba72b3a15a6154fe6ca1ada817553
 
-sdk.win_installer=installer_r22.6.2-windows.exe
-sdk.win_installer_bytes=87383126
-sdk.win_installer_checksum=2a68b8b22ecd0aba779b1581a914b395
+sdk.win_installer=installer_r23-windows.exe
+sdk.win_installer_bytes=90065639
+sdk.win_installer_checksum=4564d1f1b30c001c78a22eec40444e5f
 
 
 
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 1e87cd8..b13983b 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
 page.title=Installing the Eclipse Plugin
-adt.zip.version=22.6.3
-adt.zip.download=ADT-22.6.3.zip
-adt.zip.bytes=14590813
-adt.zip.checksum=3982259fd2cc81e53bbbe05dcd6529a7
+adt.zip.version=23.0.0
+adt.zip.download=ADT-23.0.0.zip
+adt.zip.bytes=104001830
+adt.zip.checksum=a1bc9b15b69b43bda358ea09a2feb5f7
 
 @jd:body
 
@@ -84,7 +84,7 @@
 <div class="sidebox-wrapper">
 <div class="sidebox">
 <h2>App Translations in Google Play</h2>
-<p>Google Play <a href="{@docRoot}distribute/tools/localization-checklist.html#gp-trans">App 
+<p>Google Play <a href="{@docRoot}distribute/tools/localization-checklist.html#gp-trans">App
 Translation Service</a> is available in the Developer Console to help you
 localize your app for a global user base. You can browse qualified vendors, get
 estimates, upload strings for translation, and then import the translations directly
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index 894514a..3b7a7da 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -1,5 +1,7 @@
 page.title=Android Studio
 page.tags="studio"
+page.image=images/resource-card-android-studio.png
+page.metaDescription=Learn about the new features in the beta release of our new IDE.
 @jd:body
 
 
@@ -249,36 +251,36 @@
     <td>Windows</td>
     <td>
   <a onclick="return onDownload(this)" id="win-studio"
-      href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-windows.exe">
-      android-studio-bundle-135.1078000-windows.exe
+      href="http://dl.google.com/android/studio/install/0.8.0/android-studio-bundle-135.1245622-windows.exe">
+      android-studio-bundle-135.1245622-windows.exe
       </a>
     </td>
-    <td>519082997 bytes</td>
-    <td>ac69889210c4d02ee3ccc1c0f3c5cf3c</td>
+    <td>380000036 bytes</td>
+    <td>5720baef7d492f2df7398a38dae2fa92</td>
   </tr>
 
   <tr>
     <td><nobr>Mac OS X</nobr></td>
     <td>
   <a onclick="return onDownload(this)" id="mac-studio"
-    href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-mac.dmg">
-    android-studio-bundle-135.1078000-mac.dmg
+    href="http://dl.google.com/android/studio/install/0.8.0/android-studio-bundle-135.1245622-mac.dmg">
+    android-studio-bundle-135.1245622-mac.dmg
     </a>
     </td>
-    <td>495989974 bytes</td>
-    <td>8c7b1ef376b8ca206c99823d9e8fd54d</td>
+    <td>368451923 bytes</td>
+    <td>fa9da3625db44687576c5c4e8f96280e</td>
   </tr>
 
   <tr>
     <td>Linux</td>
     <td>
   <a onclick="return onDownload(this)" id="linux-studio"
-    href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-linux.tgz">
-    android-studio-bundle-135.1078000-linux.tgz
+    href="http://dl.google.com/android/studio/install/0.8.0/android-studio-bundle-135.1245622-linux.tgz">
+    android-studio-bundle-135.1245622-linux.tgz
     </a>
     </td>
-    <td>520523870 bytes</td>
-    <td>689238d5e632fd236b13f9c6d49f0cb4</td>
+    <td>417756987 bytes</td>
+    <td>c70dd2e4035484b84f0ad0046a34f136</td>
   </tr>
   </table>
 
@@ -396,6 +398,18 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>Android Studio v0.8.0</a> <em>(June 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+    <p>Added support for Android Wear projects.</p>
+    <p>See <a href="http://tools.android.com/recent">tools.android.com</a> for a full list of changes.</p>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>Android Studio v0.5.2</a> <em>(May 2014)</em>
   </p>
 
@@ -570,7 +584,7 @@
   if (os) {
     /* set up primary ACE download button */
     $('#download-ide-button').show();
-    $('#download-ide-button').append("Download Android Studio Beta <span class='small'>v0.5.2</span>"
+    $('#download-ide-button').append("Download Android Studio Beta <span class='small'>v0.8.0</span>"
         + "<br/> <span class='small'>with the Android SDK for " + os + "</span>");
     $('#download-ide-button').click(function() {return onDownload(this,true);}).attr('href', bundlename);
 
diff --git a/docs/html/tools/revisions/build-tools.jd b/docs/html/tools/revisions/build-tools.jd
index d8abab0..0abec2e 100644
--- a/docs/html/tools/revisions/build-tools.jd
+++ b/docs/html/tools/revisions/build-tools.jd
@@ -77,6 +77,25 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>Build Tools, Revision 20.0.0</a> <em>(June 2014)</em>
+  </p>
+  <div class="toggle-content-toggleme">
+
+    <dl>
+      <dt>General Notes:</dt>
+      <dd>
+        <ul>
+          <li>Added support for Android Wear.</li>
+        </ul>
+      </dd>
+    </dl>
+
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>Build Tools, Revision 19.1.0</a> <em>(May 2014)</em>
   </p>
   <div class="toggle-content-toggleme">
diff --git a/docs/html/tools/revisions/platforms.jd b/docs/html/tools/revisions/platforms.jd
index 5d1d13b..b5495c2 100644
--- a/docs/html/tools/revisions/platforms.jd
+++ b/docs/html/tools/revisions/platforms.jd
@@ -47,6 +47,34 @@
 components will not be available for download.</p>
 
 
+<h2 id="4.4">Android 4.4W</h2>
+
+<div class="toggle-content opened">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />Revision 1</a> <em>(June 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <p>Initial release for Android Wear.</p>
+    <p>Dependencies:</p>
+    <ul>
+      <li>Android SDK Platform-tools r20 or higher is required.</li>
+      <li>Android SDK Tools 23.0 or higher is required.</li>
+    </ul>
+  </div>
+
+  <h3>Device Definitions</h3>
+
+  <p>The platform includes the following device definitions for use in creating Android Virtual
+  Devices in the <a href="{@docRoot}tools/help/avd-manager.html">AVD Manager</a>:</p>
+
+  <ul>
+    <li>Android Wear Round (320 x 320, hdpi)</li>
+    <li>Android Wear Square (320 x 320, hdpi)</li>
+  </ul>
+</div>
 
 <h2 id="4.4">Android 4.4</h2>
 
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index 124e58d..8826ce3e 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -56,6 +56,38 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 23.0.0</a> <em>(June 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 7 or higher is required if you are targeting the L Developer Preview.</li>
+      <li>Java 1.6 or higher is required if you are targeting other releases.</li>
+      <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+      <li>This version of ADT is designed for use with
+        <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r23.0.0</a>.
+        If you haven't already installed SDK Tools r23.0.0 into your SDK, use the
+        Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+      <li>Added the Android Wear tools and system images.</li>
+    </ul>
+  </dd>
+</dl>
+</div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 22.6.3</a> <em>(April 2014)</em>
   </p>
 
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index f490053..6c74a71 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -28,6 +28,37 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>SDK Tools, Revision 23.0.0</a> <em>(June 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <dl>
+    <dt>Dependencies:</dt>
+
+    <dd>
+      <ul>
+        <li>Android SDK Platform-tools revision 19 or later.</li>
+        <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+          designed for use with ADT 23.0.0 and later. If you haven't already, update your
+        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 23.0.0.</li>
+        <li>If you are developing outside Eclipse, you must have
+          <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+      </ul>
+    </dd>
+
+    <dt>General Notes:</dt>
+    <dd>
+      <ul>
+        <li>Added the Android Wear tools and system images.</li>
+      </ul>
+    </dd>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>SDK Tools, Revision 22.6.4</a> <em>(June 2014)</em>
   </p>
 
diff --git a/docs/html/training/building-wearables.jd b/docs/html/training/building-wearables.jd
new file mode 100644
index 0000000..0745c93
--- /dev/null
+++ b/docs/html/training/building-wearables.jd
@@ -0,0 +1,10 @@
+page.title=Building Apps for Wearables
+page.trainingcourse=true
+page.image=wear/images/notifications.png
+page.metaDescription=Learn how to build notifications, send and sync data, and use voice actions.
+
+@jd:body
+
+
+<p>These classes teach you how to build notifications in a handheld app that are automatically
+synced to wearables as well as how to build apps that run on wearables.</p>
\ No newline at end of file
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index c5dc3c5..4407d30 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -638,7 +638,6 @@
             </li>
         </ul>
       </li>
-
     </ul>
   </li>
   <!-- End connectivity and cloud -->
@@ -727,6 +726,90 @@
   <!-- End privacy and location -->
 
 
+  <li class="nav-section">
+    <div class="nav-section-header">
+      <a href="<?cs var:toroot ?>training/building-wearables.html">
+      <span class="small">Building Apps for</span><br/>
+              Wearables
+      </a>
+    </div>
+    <ul>
+      <li class="nav-section">
+        <div class="nav-section-header">
+          <a href="<?cs var:toroot ?>training/wearables/notifications/index.html"
+             description="How to build handheld notifications that are synced to
+             and look great on wearables."
+            >Adding Wearable Features to Notifications</a>
+        </div>
+        <ul>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/notifications/creating.html">Creating a Notification</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/notifications/voice-input.html">Receiving Voice Input in a Notification</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/notifications/pages.html">Adding Pages to a Notification</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/notifications/stacks.html">Stacking Notifications</a>
+          </li>
+        </ul>
+      </li>
+
+      <li class="nav-section">
+        <div class="nav-section-header">
+          <a href="<?cs var:toroot ?>training/wearables/apps/index.html"
+             description="How to build apps that run directly on wearables."
+            >Creating Wearable Apps</a>
+        </div>
+        <ul>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/apps/creating.html">Creating and Running a Wearable App</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/apps/layouts.html">Creating Custom Layouts</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/apps/voice.html">Adding Voice Capabilities</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/apps/packaging.html">Packaging Wearable Apps</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/apps/bt-debugging.html">Debugging over Bluetooth</a>
+          </li>
+        </ul>
+      </li>
+
+      <li class="nav-section">
+        <div class="nav-section-header">
+          <a href="<?cs var:toroot ?>training/wearables/data-layer/index.html"
+             description="How to sync data between handhelds and wearables."
+            >Sending and Syncing Data</a>
+        </div>
+        <ul>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/data-layer/accessing.html">Accessing the Wearable Data Layer</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/data-layer/data-items.html">Syncing Data Items</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/data-layer/assets.html">Transferring Assets</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/data-layer/messages.html">Sending and Receiving Messages</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/wearables/data-layer/events.html">Handling Data Layer Events</a>
+          </li>
+        </ul>
+      </li>
+    </ul>
+  </li>
+
+  <!-- End Building for wearables -->
 
   <li class="nav-section">
     <div class="nav-section-header">
diff --git a/docs/html/training/wearables/apps/bt-debugging.jd b/docs/html/training/wearables/apps/bt-debugging.jd
new file mode 100644
index 0000000..8d09c43
--- /dev/null
+++ b/docs/html/training/wearables/apps/bt-debugging.jd
@@ -0,0 +1,92 @@
+page.title=Debugging over Bluetooth
+
+@jd:body
+
+<div id="tb-wrapper">
+  <div id="tb">
+
+    <!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+    <h2>This lesson teaches you to</h2>
+    <ol>
+      <li><a href="#SetupDevices">Set Up Devices for Debugging</a></li>
+      <li><a href="#SetupSession">Set Up a Debugging Session</a></li>
+      <li><a href="#DebugApp">Debug Your App</a></li>
+    </ol>
+    <h2>You should also read</h2>
+    <ul>
+      <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li>
+    </ul>
+  </div>
+</div>
+
+<p>You can debug your wearable over Bluetooth by routing it's debug output to the
+handheld device that's connected to your development machine.</p>
+
+<h2 id="SetupDevices">Setup Devices for Debugging</h2>
+<ol>
+  <li>Enable USB debugging on the handheld:
+    <ul>
+      <li>Open the Settings app and scroll to the bottom.</li>
+      <li>If it doesn't have a Developer Options setting, tap <b>About Phone</b>
+      (or <b>About Tablet</b>), scroll to the bottom, and tap the build number 7 times.</li>
+      <li>Go back and tap <b>Developer Options</b>.</li>
+      <li>Enable <b>USB debugging</b>.</li>
+    </ul>
+  </li>
+  <li>Enable Bluetooth debugging on the wearable:
+    <ol>
+      <li>Tap the home screen twice to bring up the Wear menu. </li>
+      <li>Scroll to the bottom and tap <b>Settings</b>.</li>
+      <li>Scroll to the bottom. If there's no <b>Developer Options</b> item, tap <b>About</b>,
+      and then tap the build number 7 times.</li>
+      <li>Tap the <b>Developer Options</b> item.</li>
+      <li>Enable <b>Debug over Bluetooth</b>.</li>
+    </ol>
+  </li>
+</ol>
+
+<h2 id="SetupSession">Set Up a Debugging Session</h2>
+<ol>
+ <li>On the handheld, open the Android Wear companion app.</li>
+ <li>Tap the menu on the top right and select <b>Settings</b>.</li>
+ <li>Enable <b>Debugging over Bluetooth</b>. You should see a tiny status summary appear under the
+ option:
+ <pre>
+Host: disconnected
+Target: connected
+</pre>
+</li>
+<li>Connect the handheld to your machine over USB and run:
+<pre>
+adb forward tcp:4444 localabstract:/adb-hub; adb connect localhost:4444
+</pre>
+
+<p class="note"><b>Note</b>: You can use any available port that you have access to.</p>
+</li>
+</ol>
+<p>
+In the Android Wear companion app, you should see the status change to:</p>
+<pre>
+Host: connected
+Target: connected
+</pre>
+
+<h2 id="#debug">Debug Your App</h2>
+
+Your wearable should show up as <code>localhost:4444</code> when running <code>adb devices</code>.
+
+To run any <code>adb</code> command, use this format:
+
+<pre>adb -s localhost:4444 &lt;command&gt; </pre>
+
+<p>If there are no other devices connected over TCP/IP (namely emulators),  you can shorten the command
+to:</p>
+<pre>
+adb -e &lt;command&gt;
+</pre>
+<p>For example:</p>
+<pre>
+adb -e logcat
+adb -e shell
+adb -e bugreport
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/wearables/apps/creating.jd b/docs/html/training/wearables/apps/creating.jd
new file mode 100644
index 0000000..841f24a
--- /dev/null
+++ b/docs/html/training/wearables/apps/creating.jd
@@ -0,0 +1,184 @@
+page.title=Creating and Running a Wearable App
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#SetupEmulator">Set Up an Android Wear Emulator</a></li>
+  <li><a href="#SetupDevice">Set Up an Android Wear Device</a></li>
+  <li><a href="#CreateProject">Create a Project</a></li>
+  <li><a href="#Libraries">Include the Correct Libraries</a></li>
+</ol>
+<h2>Dependencies and Prerequisites</h2>
+  <ul>
+    <li>Android Studio 0.8 or later and Gradle 0.12 or later</li>
+  </ul>
+</div>
+</div>
+
+<p>Wearable apps run directly on the wearable device, giving you access to low-level
+hardware such as sensors, activities, services, and more, right
+on the wearable.</p>
+
+<p>A companion handheld app that contains the
+wearable app is also required when you want to publish to the Google Play store.
+Wearables don't support the Google Play store, so users download the companion handheld app,
+which automatically pushes the wearable app to the wearable. The handheld app is also
+useful for doing heavy processing, network actions, or other work and
+sending the results to the wearable.
+</p>
+
+<p>This lesson goes over how to set up a device or emulator and create one project to contain
+both your wearable and handheld apps.
+</p>
+
+
+<h2 id="SetupEmulator">Set Up an Android Wear Emulator or Device</h2>
+<p>We recommend that you develop on real hardware so you can better
+gauge the user experience. However, the emulator lets you test out different
+types of screen shapes, which is useful for testing.</p>
+
+<h3>Set up an Android Wear Virtual Device</h3>
+
+<p>To set up an Android Wear virtual device:</p>
+<ol>
+  <li>Click <b>Tools > Android > AVD Manager</b>.</li>
+  <li>Click <b>Create...</b>.</li>
+  <li>Fill in the following details for the AVD you want to specify and leave the rest
+  of the fields with their default values:
+    <ol>
+      <li><b>AVD Name</b> - A name for your AVD</li>
+      <li><b>Device</b> - Android Wear Round or Square device types</li>
+      <li><b>Target</b> - Android 4.4W - API Level 20</li>
+      <li><b>CPU/ABI</b> - Android Wear ARM (armeabi-v7a)</li>
+      <li><b>Keyboard</b> - Select <b>Hardware keyboard present</b></li>
+      <li><b>Skin</b> - AndroidWearRound or AndroidWearSquare depending on the selected device type</li>
+      <li><b>Snapshot</b> - Not selected</li>
+      <li><b>Use Host GPU</b> - Selected, to support custom activities for wearable notifications</li>
+    </ol>
+  </li>
+  <li>Click <b>OK</b>.</li>
+<li>Start the emulator:
+<ol>
+  <li>Select the virtual device you just created.</li>
+  <li>Click <b>Start...</b>, then click <b>Launch</b>.</li>
+  <li>Wait until the emulator initializes and shows the Android Wear home screen.</li>
+</ol>
+</li>
+<li>Pair Your handheld with the emulator:
+<ol>
+  <li>On your handheld, install the Android Wear app from Google Play.</li>
+  <li>Connect the handheld to your machine through USB.</li>
+  <li>Forward the AVD's communication port to the connected handheld device (you must
+  do this every time the handheld is connected):
+  <pre>adb -d forward tcp:5601 tcp:5601</pre>
+  </li>
+  <li>Start the Android Wear app on your handheld device and connect to the emulator.</li>
+  <li>Tap the menu on the top right corner of the Android Wear app and select
+  <b>Demo Cards</b>.</li>
+  <li>The cards you select appear as notifications on the home screen of the emulator.</li>
+</ol>
+</li>
+</ol>
+
+<h3 id="SetupDevice">Set Up an Android Wear Device</h3>
+<p>To set up an Android Wear device:</p>
+<ol>
+  <li>Install the Android Wear app, available on Google Play, on your handheld.</li>
+  <li>Follow the app's instructions to pair your handheld with your wearable.
+  This allows you to test out synced handheld notifications, if you're building them.</li>
+  <li>Connect the wearable to your machine through USB, so you can install apps directly to it
+  as you develop.</li>
+</ol>
+
+<h2 id="CreateProject">Create a Project</h2>
+
+<p>To begin development, create an app project that contains
+ wearable and handheld app modules. In Android Studio, click <b>File</b> >
+ <b>New Project</b> and follow the Project Wizard instructions, as described in
+ <a href="{@docRoot}sdk/installing/create-project.html">Creating a
+Project</a>. As you follow the wizard, enter the following information:</p>
+
+<ol>
+  <li>In the <b>Configure your Project</b> window, enter a name for your app and a package
+  name.</li>
+  <li>In the <b>Form Factors</b> window:
+    <ul>
+      <li>Select <b>Phone and Tablet</b> and select <b>API 8: Android 2.2 (Froyo)</b>
+      under <b>Minimum SDK</b>.</li>
+      <li>Select <b>Wear</b> and select <b>API 20: Android 4.4 (KitKat Wear)</b>
+      under <b>Minimum SDK</b>.</li>
+    </ul>
+  </li>
+  <li>In the first <b>Add an Activity</b> window, add a blank activity for mobile.</li>
+  <li>In the second <b>Add an Activity</b> window, add a blank activity for Wear.
+
+  <p>When the wizard completes, Android Studio creates a new project with two modules, <b>mobile</b> and
+  <b>wear</b>. You now have a project for both your handheld and wearable apps that you can create activities,
+  services, custom layouts, and much more in. On the handheld app, you do most of the heavy lifting,
+  such as network communications, intensive processing, or tasks that require long
+  amounts of user interaction. When these are done,
+  you usually notify the wearable of the results through notifications or by syncing and sending
+  data to the wearable.</p>
+
+  <p class="note"><b>Note:</b> The <b>wear</b> module also contains a "Hello World" activity that uses a
+  <code>WatchViewStub</code> that inflates a layout based on whether the device's screen
+  is round or square. The <code>WatchViewStub</code> class is one of the UI widgets that's provided
+  by the <a href="{@docRoot}training/wearables/apps/layouts#UiLibrary">wearable support library</a>.</p>
+</li>
+
+<h2 id="Install">Install the Wearable app</h2>
+
+<p>When developing, you install apps directly to the wearable like with handheld apps. Use
+either <code>adb install</code> or the <b>Play</b> button on Android Studio.</p>
+
+<p>When you're ready to publish your app to users, you embed the wearable app inside of the
+handheld app. When users install the handheld app from Google Play, a connected wearable automatically
+receives the wearable app.</p>
+
+<p class="note"><b>Note:</b> The automatic installation of wearable apps
+does not work when you are signing apps with a debug key and only works with release keys. See
+<a href="{@docRoot}traiing/wearables/packaging.html">Packaging Wearable Apps</a> for
+complete information on how to properly package wearable apps.</p>
+
+<li>
+To install the "Hello World" app to the wearable, select <b>wear</b> from the <b>Run/Debug
+configuration</b> drop-down menu and click the <b>Play</b> button. The activity shows up on the
+wearable and prints out "Hello world!"
+</li></ol>
+<h2 id="Libraries">Include the Correct Libraries</h2>
+
+<p>As part of the Project Wizard, the correct
+dependencies are imported for you in the appropriate module's <code>build.gradle</code> file.
+However, these dependencies are not required, so read the following descriptions to find out if you need them or not:</p>
+
+<b>Notifications</b>
+<p>The <a href="{@docRoot}tools/support-library/features.html#v4">The
+Android v4 support library</a> (or v13, which includes v4)
+contains the APIs to extend your existing notifications on handhelds to support wearables.</p>
+
+<p>For notifications that appear only on
+the wearable (meaning, they are issued by an app that runs on the wearable), you can just use the
+standard framework APIs (API Level 20) on the wearable and remove the support library
+dependency in the <b>mobile</b> module of your project.
+</p>
+
+<b>Wearable Data Layer</b>
+<p>To sync and send data between wearables and handhelds with the Wearable Data Layer APIs,
+you need the latest version of
+<a href="{@docRoot}google/play-services/setup.html">Google Play services</a>.
+If you're not using these APIs, remove the dependency from both modules.</p>
+
+<b>Wearable UI support library</b>
+<p>This is an unofficial library that includes UI widgets designed for wearables. We encourage you
+to use them in your apps, because they exemplify best practices, but they can still
+change at any time. However, if the libraries are updated, your apps won't break since they are compiled
+into your app. To get new features from an updated library, you just need to
+statically link the new version and update your app accordingly.
+This library is only applicable if you create wearable apps.
+</p>
+
+<p>In the next lessons, you'll learn how to create layouts designed for wearables as well as how
+to use the various voice actions that are supported by the platform.</p>
diff --git a/docs/html/training/wearables/apps/index.jd b/docs/html/training/wearables/apps/index.jd
new file mode 100644
index 0000000..3a4eb70
--- /dev/null
+++ b/docs/html/training/wearables/apps/index.jd
@@ -0,0 +1,74 @@
+page.title=Creating Wearable Apps
+page.image=wear/images/notifications.png
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dependencies and Prerequisites</h2>
+  <ul>
+    <li>Android Studio 0.8 or later and Gradle 0.12 or later</li>
+  </ul>
+</div>
+</div>
+
+<p>
+Wearable apps run directly on the device, giving you access to hardware such as sensors and the
+GPU. They are fundamentally the same as apps built for other devices using the Android SDK, but
+differ greatly in design and usability and the amount of functionality provided.
+These are the main differences between handheld and wearable apps:</p>
+
+<ul>
+  <li>The system enforces a timeout period. If you are displaying an activity and user's don't
+  interact with it, the device sleeps. When it wakes back up, the Wear home screen is displayed
+  instead of your activity. If you need to show something persistent, create a notification in the
+  context stream instead.</li>
+  <li>Wearable apps are relatively small in size and functionality compared to handheld apps.
+  They contain only what makes sense on the wearable, which is usually a small
+  subset of the corresponding handheld app. In general, you should carry out operations on the
+  handheld when possible and send the results to the wearable.
+  </li>
+  <li>Users don't download apps directly onto the wearable. Instead, you bundle
+  the wearable app inside the handheld app. When users install the handheld app,
+  the system automatically installs the wearable app. However, for development
+  purposes, you can still install the wearable app directly to the wearable.</li>
+  <li><p>Wearable apps can access much of the standard Android APIs, but don't support
+  the following APIs:</p>
+  <ul>
+    <li>{@link android.webkit}</li>
+    <li>{@link android.print}</li>
+    <li>{@link android.app.backup}</li>
+    <li>{@link android.appwidget}</li>
+    <li>{@link android.hardware.usb}</li>
+  </ul>
+  <p>
+  You can check if a wearable supports a feature by calling
+  {@link android.content.pm.PackageManager#hasSystemFeature hasSystemFeature()}
+  before trying to use an API.</p>
+</li>
+</ul>
+
+<p class="note"><b>Note:</b> We recommend using Android Studio for Android Wear development
+as it provides project setup, library inclusion, and packaging conveniences that aren't available
+in ADT. The rest of this training assumes you're using Android Studio.
+</p>
+
+<h2>Lessons</h2>
+  <dl>
+    <dt><a href="{@docRoot}training/wearables/apps/creating.html">Creating and Running a Wearable App</a></dt>
+      <dd>Learn how to create an Android Studio project that
+      contains both the wearable and handheld app modules and how to run the app on a device
+      or emulator.</dd>
+    <dt><a href="{@docRoot}training/wearables/apps/activity.html">Creating Custom Layouts</a></dt>
+      <dd>Learn how to create and display custom layouts for notifications and
+      activities.</dd>
+    <dt><a href="{@docRoot}training/wearables/apps/voice.html">Adding Voice Capabilities</a></dt>
+      <dd>Learn how to launch an activity with a voice actions and how to start the
+      system speech recognizer app to obtain free-form voice input.</dd>
+    <dt><a href="{@docRoot}training/wearables/apps/packaging.html">Packaging Wearable Apps</a></dt>
+      <dd>Learn how to package a wearable app inside a
+      handheld app. This allows the system to install the wearable app automatically when
+      users install the companion handheld app from the Google Play store.</dd>
+    <dt><a href="{@docRoot}training/wearables/apps/packaging.html">Debugging over Bluetooth</a></dt>
+      <dd>Learn how to debug your wearable over Bluetooth instead of USB.</dd>
+  </dl>
\ No newline at end of file
diff --git a/docs/html/training/wearables/apps/layouts.jd b/docs/html/training/wearables/apps/layouts.jd
new file mode 100644
index 0000000..4bf9cde
--- /dev/null
+++ b/docs/html/training/wearables/apps/layouts.jd
@@ -0,0 +1,134 @@
+page.title=Creating Custom Layouts
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#CustomNotifications">Create custom notifications</a></li>
+  <li><a href="#UiLibrary">Create Layouts with the Wearable UI Library</li>
+</ol>
+
+<!--STOPSHIP: link these -->
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li>
+</ul>
+
+</div>
+</div>
+
+<p>Creating layouts for wearables is the same as handheld devices, except you have to design
+for the screen size and for glanceability. Do not port functionality
+and the UI from a handheld app and expect a good experience. You should create custom layouts
+only when necessary. Read the <a href="{@docRoot}design/wear/index.html">design guidelines</a>
+for information on how to design great wearable apps.</p>
+
+<h2 id="CustomNotifications">Create Custom Notifications</h2>
+
+<p>
+In general, you should create notifications on the handheld and let them
+automatically sync to the wearable. This lets you build your notifications
+once and have them appear on many types of devices (not just wearables, but
+eventually Auto and TV) without having to design them for different
+form factors.</p>
+
+<p>If the standard notification styles don't work for you (such as
+{@link android.support.v4.app.NotificationCompat.BigTextStyle} or
+{@link android.support.v4.app.NotificationCompat.InboxStyle}), you can display an activity with
+a custom layout. You can only create and issue custom notifications on the wearable, and the
+system does not sync these notifications to the handheld.</p>
+
+<p clas="note"><b>Note:</b> When creating custom notifications on the wearable, you can use the
+standard notification APIs (API Level 20) instead of the Support Library.
+</p>
+
+<p>To create a custom notification:</p>
+<ol>
+  <li>Create a layout and set it as the content view for the activity
+  that you want to display.
+<pre>
+public void onCreate(Bundle bundle){
+    ...
+    setContentView(R.layout.notification_activity);
+}
+</pre>
+  </li>
+  <li>Define necessary properties for the activity in the Android manifest to allow
+  the activity to be displayed in the wearable's context stream process. You need to declare the
+  activity to be exportable, be embeddable, and have an empty task affinity. We also recommend
+  setting the theme to <code>Theme.DeviceDefault.Light</code>. For example:</li>
+<pre>
+&lt;activity android:name="com.example.MyDisplayActivity"
+     android:exported="true"
+     android:allowEmbedded="true"
+     android:taskAffinity=""
+     android:theme="@android:style/Theme.DeviceDefault.Light" /&gt;
+</pre>
+  </li>
+  <li>Create a {@link android.app.PendingIntent} for the activity that you want to display.
+  For example:
+<pre>
+Intent notificationIntent = new Intent(this, NotificationActivity.class);
+PendingIntent notificationPendingIntent = PendingIntent.getActivity(this, 0, notificationIntent,
+        PendingIntent.FLAG_UPDATE_CURRENT);
+</pre>
+  </li>
+  <li>Build a {@link android.app.Notification} and call
+  {@link android.app.Notification.WearableExtender#setDisplayIntent setDisplayIntent()}
+  providing the {@link android.app.PendingIntent}. The system uses this
+  {@link android.app.PendingIntent} to launch the activity when
+  users view your notification.
+  </li>
+  <li>Issue the notification using the
+  {@link android.app.NotificationManager#notify notify()} method.
+  <p class="note"><b>Note:</b> The system initially displays your notification with
+  a standard template. This template works well on all watchfaces. When users swipe the notification
+  up to view it, they'll then see your activity for the notification.</p>
+  </li>
+</ol>
+<h2 id="UiLibrary">Create Layouts with the Wearable UI Library</h2>
+<p>
+There's an unofficial UI library that is automatically included when you create your wearable
+app with the Android Studio Project Wizard. You can also add the library to your <code>build.gradle</code>
+file with the following dependency declaration:
+
+<pre>
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    <b>compile 'com.google.android.support:wearable:+'</b>
+    compile 'com.google.android.gms:play-services-wearable:+'
+}
+</pre>
+This library helps you build UIs that are designed for wearables. Here are some of the major classes:
+</p>
+
+<ul>
+    <li><code>BoxInsetLayout</code> - A FrameLayout that's aware of screen shape and can box its
+    children in the center square of a round screen.</li>
+    <li><code>CardFragment</code> - A fragment that presents content within an expandable,
+    vertically scrollable card.</li>
+    <li><code>CircledImageView</code> - An image view surrounded by a circle.</li>
+    <li><code>ConfirmationActivity</code> - An activity that displays confirmation animations after the user
+    completes an action.</li>
+    <li><code>DismissOverlayView</code> - A view for implementing long-press-to-dismiss.</li>
+    <li><code>GridViewPager</code> - A layout manager that allows the user to both vertically and
+    horizontally through pages of data. You supply an implementation of a GridPagerAdapter to
+    generate the pages that the view shows.</li>
+    <li><code>GridPagerAdapter</code> - An adapter that supplies pages to a GridViewPager.</li>
+    <li><code>FragmentGridPagerAdapter</code> - An implementation of GridPagerAdapter that
+    represents each page as a fragment.</li>
+    </li>
+    <li><code>WatchViewStub</code> - A class that can inflate a specific layout,
+    depending on the shape of the device's screen.</li>
+    <li><code>WearableListView</code> - An alternative version of ListView that is optimized for
+    ease of use on small screen wearable devices. It displays a vertically scrollable list of items,
+    and automatically snaps to the nearest item when the user stops scrolling.
+    </li>
+</ul>
+
+<p class="note"><a href="{@docRoot}shareables/training/wearable-support-docs.zip">Download the full API
+reference documentation</a> for the classes above. The documentation goes over how to use
+each UI widget.</p>
diff --git a/docs/html/training/wearables/apps/packaging.jd b/docs/html/training/wearables/apps/packaging.jd
new file mode 100644
index 0000000..ea29c9d
--- /dev/null
+++ b/docs/html/training/wearables/apps/packaging.jd
@@ -0,0 +1,156 @@
+page.title=Packaging Wearable Apps
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#Studio">Package with Android Studio</a></li>
+  <li><a href="#PackageManually">Package Manually</a></li>
+  <li><a href="#AssetCompression">Turn off Asset Compression</a></li>
+</ol>
+</div>
+</div>
+
+<p>When publishing to users, you must package a wearable app inside of a handheld app, 
+because users cannot browse and install apps directly on the wearable. If packaged properly,
+when users download the handheld app, the system automatically pushes the wearable app to the
+paired wearable.
+</p>
+
+<p class="note"><b>Note:</b> This feature doesn't work when you are signing your apps with
+a debug key when developing. While developing, installing apps with <code>adb install</code> or
+Android Studio directly to the wearable is required.</p>
+
+
+<h2 id="Studio">Package with Android Studio</h2>
+<p>To properly package a wearable app in Android Studio:</p>
+
+<ol>
+  <li>Declare a Gradle dependency in the handheld app's <code>build.gradle</code> file
+  that points to the wearable app module:
+<pre>
+dependencies {
+   compile 'com.google.android.gms:play-services:5.0.+@aar'
+   compile files('../../prebuilt-libs/android-support-v4.jar')
+   <b>wearApp project(':wearable')</b>
+}
+</pre>
+  </li>
+  <li>Click <b>Build > Generate Signed APK...</b> and follow the on-screen instructions
+  to specify your release keystore and sign your app. Android Studio exports the signed
+  handheld app with the wearable app embedded in it automatically into your project's root folder.
+
+  <p>Alternatively, you can create a <code>signingConfig</code> rule in the wearable and handheld
+  modules' <code>build.gradle</code> file to sign them with your release key. Both apps must be
+  signed to have the automatic pushing of the wearable app work.
+
+<pre>
+android {
+  ...
+  signingConfigs {
+    release {
+      keyAlias 'myAlias'
+      keyPassword 'myPw'
+      storeFile file('path/to/release.keystore')
+      storePassword 'myPw'
+    }
+  }
+  buildTypes {
+    release {
+      ...
+      signingConfig signingConfigs.release
+    }d
+  }
+  ...
+}
+</pre>
+  <p>Build the handheld app by clicking the Gradle button on the right vertical toolbar of
+  Android Studio and running the <b>assembleRelease</b> task. The task is located under
+  <b>Project name > Handheld module name > assembleRelease</b>.
+  </p>
+
+<p class="note"><b>Note:</b>This example embeds the password in your Gradle file, which might be undesirable. See
+<a href="{@docRoot}sdk/installing/studio-build.html#configureSigning">Configure signing settings</a>
+for information about how to create an environment variable for the passwords instead.
+</p>
+</ol>
+
+
+<h3>Signing the wearable and handheld app separately</h3>
+<p>If your build process requires signing the wearable app separately from the handheld app,
+you can declare the following Gradle rule in the handheld module's <code>build.gradle</code> to
+embed the previously-signed wearable app:</p>
+
+<pre>
+dependencies {
+  ...
+  wearApp files('/path/to/wearable_app.apk')
+}
+</pre>
+
+<p>You then sign your handheld app in any manner you wish (either with the Android Studio
+<b>Build > Generate Signed APK...</b> menu item or with Gradle <code>signingConfig</code> rules as
+described in the previous section.</p>
+
+<h2 id="PackageManually">Package Manually</h2>
+<p>
+It's still possible to package the wearable app into the handheld app manually
+if you are using another IDE or another method of building.
+</p>
+
+<ol>
+  <li>Copy the signed wearable app into your handheld project's <code>assets/</code> directory,
+  referred to as <code>path/to/wearable_app.apk</code>.</li>
+  <li>Create a <code>res/xml/wearable_app_desc.xml</code> file that contains the version and
+  path information of the wearable app:
+<pre>
+&lt;wearableApp package="com.google.android.wearable.myapp"&gt;
+  &lt;versionCode>1&lt;/versionCode&gt;
+  &lt;versionName>1.0&lt;/versionName&gt;
+  &lt;path>path/to/wearable_app.apk&lt;/path&gt;
+&lt;/wearableApp&gt;
+</pre>
+<p>
+The <code>package</code>, <code>versionCode</code>, and <code>versionName</code> are the
+same as values specified in the wearable app's <code>AndroidManifest.xml</code> file. 
+The path is the full path of <code>wearable_app.apk</code>, relative to the <code>assets/</code>
+directory.
+</p>
+</li>
+<li>
+Add a <code>meta-data</code> tag to your handheld app's <code>&lt;application&gt;</code> tag to
+reference the <code>wearable_app_desc.xml</code> file.
+<pre>
+  &lt;meta-data android:name="com.google.android.wearable.myapp" 
+                 android:resource="&#64;xml/wearable_app_desc"/&gt;
+</pre>
+</li>
+<li>Build and sign the handheld app.</li>
+</ol>
+
+<h2 id="AssetCompression">Turn off Asset Compression</h2>
+<p>
+Many build tools automatically compress any files added to the <code>assets/</code>
+directory of an Android app. Because the wearable APK is already zipped, these tools re-compress the
+wearable APK and the wearable app installer can no longer read the wearable app.
+</p>
+
+<p> When this happens, the installation fails. On the handheld app, the <code>PackageUpdateService</code>
+logs the following error: "this file cannot be opened as a file descriptor; it is probably compressed."
+
+<p> To prevent this error in Android Studio, update your handheld app's <code>build.gradle</code> file
+with the following declaration:
+</p>
+
+<pre>
+android {
+  aaptOptions {
+    noCompress "apk"
+  }
+}
+</pre>
+
+<p>If you are using another build process, ensure that you don't doubly compress the wearable app.</p>
\ No newline at end of file
diff --git a/docs/html/training/wearables/apps/voice.jd b/docs/html/training/wearables/apps/voice.jd
new file mode 100644
index 0000000..3dea5d7
--- /dev/null
+++ b/docs/html/training/wearables/apps/voice.jd
@@ -0,0 +1,274 @@
+page.title=Adding Voice Capabilities
+@jd:body
+
+<div id="tb-wrapper">
+  <div id="tb">
+
+    <!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+    <h2>This lesson teaches you to</h2>
+    <ol>
+      <li><a href="#SystemProvided">Declare System-provided Voice Actions</a></li>
+      <li><a href="#AppProvided">Declare App-provided Voice Actions</a></li>
+      <li><a href="#FreeFormSpeech">Obtaining Free-form Speech Input</a></li>
+    </ol>
+    <h2>You should also read</h2>
+    <ul>
+      <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li>
+    </ul>
+  </div>
+</div>
+
+<p>Voice actions are an important part of the wearable experience. They let users carry
+out actions hands-free and quickly. Wear provides two types of voice actions:</p>
+
+<dl>
+  <dt><b>System-provided</b></dt>
+  <dd>These voice actions are task-based and are built
+  into the Wear platform. You filter for them in the activity that you want to start when the
+  voice action is spoken. Examples include "Take a note" or "Set an alarm".</dd>
+  <dt><b>App-provided</b></dt>
+  <dd>These voice actions are app-based, and you declare them just like a launcher icon.
+  Users say "Start <Your App Name>" to use these voice actions and an activity that you specify
+  starts.</dd>
+</dl>
+
+<h2 id="SystemProvided" style="clear:right">Declare System-provided Voice Actions</h2>
+<p>
+The Android Wear platform provides several voice intents that are based on user actions such
+as "Take a note" or "Set an alarm". This allows users to say what they want to do and let
+the system figure out the best activity to start.</p>
+
+<p>When users speak the voice action, your app can filter for the intent that is fired to start
+an activity. If you want to start a service to do something in the background, show an activity as
+a visual cue and start the service in the activity. Make sure to call
+{@link android.app.Activity#finish finish()} when you want to get rid of the visual cue.
+</p>
+
+<p>For example, for the "Take a note" command, declare this intent filter to start an activity
+named <code>MyNoteActivity</code>:
+</p>
+
+<pre>
+  &lt;activity android:name="MyNoteActivity"&gt;
+      &lt;intent-filter&gt;
+          &lt;action android:name="android.intent.action.SEND" /&gt;
+          &lt;category android:name="com.google.android.voicesearch.SELF_NOTE" /&gt;
+      &lt;/intent-filter&gt;
+  &lt;/activity&gt;
+</pre>
+
+<p>Here is a list of the voice intents supported by the Wear platform:</p>
+
+<table>
+  <tr>
+    <th>Name</th>
+    <th>Example Phrases</th>
+    <th>Intent</th>
+  </tr>
+
+  <tr>
+    <td>Call a car/taxi</td>
+    <td>"OK Google, get me a taxi"<br/><br/>"OK Google, call me a car"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd>
+          <code>com.google.android.gms.actions.RESERVE_TAXI_RESERVATION</code>
+        </dd>
+      </dl>
+    </td>
+  </tr>
+
+  <tr>
+    <td>Take a note</td>
+    <td>"OK Google, take a note"<br/><br/>"OK Google, note to self"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>android.intent.action.SEND</code></dd>
+        <dt>Category</dt>
+        <dd><code>com.google.android.voicesearch.SELF_NOTE</code></dd>
+        <dt>Extras</dt>
+        <dd><code>android.content.Intent.EXTRA_TEXT</code> - a string with note body</dd>
+      </dl>
+   </td>
+  </tr>
+
+  <tr>
+    <td>Set alarm</td>
+    <td>"OK Google, set an alarm for 8 AM"<br/><br/>"OK Google, wake me up at 6 tomorrow"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>android.intent.action.SET_ALARM</code></dd>
+        <dt>Extras</dt>
+        <dd><code>android.provider.AlarmClock.EXTRA_HOUR</code> - an integer with the hour of
+        the alarm.
+        <p><code>android.provider.AlarmClock.EXTRA_MINUTES</code> -
+        an integer with the minute of the alarm
+        <p>(these 2 extras are optional, either none or
+        both are provided)</p></dd>
+
+      </dl>
+   </td>
+  </tr>
+
+  <tr>
+    <td>Set timer</td>
+    <td>"Ok Google, set a timer for 10 minutes"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>android.provider.AlarmClock.ACTION_SET_TIMER</code></dd>
+        <dt>Extras</dt>
+        <dd><code>android.provider.AlarmClock.EXTRA_LENGTH</code> - an integer in the range of
+        1 to 86400 (number of seconds in 24 hours) representing the length of the timer </dd>
+      </dl>
+   </td>
+  </tr>
+
+  <tr>
+    <td>Start/Stop a bike ride</td>
+    <td>"OK Google, start cycling"<br/><br/>"OK Google, start my bike ride"<br/><br/>"OK Google, stop cycling"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>vnd.google.fitness.TRACK</code></dd>
+        <dt>Mime Type</dt>
+        <dd><code>vnd.google.fitness.activity/biking</code></dd>
+        <dt>Extras</dt>
+        <dd><code>actionStatus</code> - a string with the value <code>ActiveActionStatus</code>
+        when starting and <code>CompletedActionStatus</code> when stopping.</dd>
+      </dl>
+   </td>
+  </tr>
+
+  <tr>
+    <td>Start/Stop a run</td>
+    <td>"OK Google, track my run"<br/><br/>"OK Google, start running"<br/><br/>"OK Google, stop running"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>vnd.google.fitness.TRACK</code></dd>
+        <dt>MimeType</dt>
+        <dd><code>vnd.google.fitness.activity/running</code></dd>
+        <dt>Extras</dt>
+        <dd><code>actionStatus</code> - a string with the value <code>ActiveActionStatus</code>
+        when starting and <code>CompletedActionStatus</code> when stopping</dd>
+      </dl>
+   </td>
+  </tr>
+
+
+  <tr>
+    <td>Start/Stop a workout</td>
+    <td>"OK Google, start a workout"<br/><br/>"OK Google, track my workout"<br/><br/>"OK Google, stop workout"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>vnd.google.fitness.TRACK</code></dd>
+        <dt>MimeType</dt>
+        <dd><code>vnd.google.fitness.activity/other</code></dd>
+        <dt>Extras</dt>
+        <dd><code>actionStatus</code> - a string with the value <code>ActiveActionStatus</code>
+        when starting and <code>CompletedActionStatus</code> when stopping</dd>
+        </dd>
+      </dl>
+   </td>
+  </tr>
+
+  <tr>
+    <td>Show heart rate</td>
+    <td>"OK Google, what’s my heart rate?"<br/><br/>"OK Google, what’s my bpm?"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>vnd.google.fitness.VIEW</code></dd>
+        <dt>Mime Type</dt>
+        <dd><code>vnd.google.fitness.data_type/com.google.heart_rate.bpm</code></dd>
+        </dd>
+      </dl>
+   </td>
+  </tr>
+
+  <tr>
+    <td>Show step count</td>
+    <td>"OK Google, how many steps have I taken?"<br/><br/>"OK Google, what’s my step count?"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>vnd.google.fitness.VIEW</code></dd>
+        <dt>Mime Type</dt>
+        <dd><code>vnd.google.fitness.data_type/com.google.step_count.cumulative</code></dd>
+        </dd>
+      </dl>
+   </td>
+  </tr>
+
+</table>
+
+<p>
+For documentation on registering for platform intents and accessing the extras information
+contained in them, see <a href="{@docRoot}guide/components/intents-common.html">Common intents</a>.
+</p>
+
+<h2 id="AppProvided">Declare App-provided Voice Actions</h2>
+<p>
+If none of the platform voice intents work for you, you can start your apps directly with
+a "Start MyActivityName" voice action. </p>
+
+<p>Registering for a "Start" action is the same as registering
+for a launcher icon on a handheld. Instead of requesting an app icon in a launcher,
+your app requests a voice action instead.</p>
+
+<p>To specify the text to say after "Start", specify a <code>label</code> attribute for the activtiy
+that you want to start. For example, this intent filter recognizes the
+"Start MyRunningApp" voice action and launches <code>StartRunActivity</code>.
+</p>
+
+<pre>
+&lt;application&gt;
+  &lt;activity android:name="StartRunActivity" android:label="MyRunningApp"&gt;
+      &lt;intent-filter&gt;
+          &lt;action android:name="android.intent.action.MAIN" /&gt;
+          &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
+      &lt;/intent-filter&gt;
+  &lt;/activity&gt;
+&lt;/application&gt;
+</pre>
+
+<h2 id="FreeFormSpeech">Obtaining Free-form Speech Input</h2>
+<p>In addition to using voice actions to launch activities, you can also call the system's
+built-in Speech Recognizer activity to obtain speech input from users. This is useful to obtain input
+from users and then process it, such as doing a search or sending it as a message.</p>
+
+In your app, you call {@link android.app.Activity#startActivityForResult startActivityForResult()} using
+the {@link android.speech.RecognizerIntent#ACTION_RECOGNIZE_SPEECH} action. This starts the
+ and then handle the result
+in {@link android.app.Activity#onActivityResult onActivityResult()}.
+<pre>
+private static final int SPEECH_REQUEST_CODE = 0;
+
+// Create an intent that can start the Speech Recognizer activity
+private void displaySpeechRecognizer() {
+    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
+            RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+// Start the activity, the intent will be populated with the speech text
+    startActivityForResult(intent, SPEECH_REQUEST_CODE);
+}
+
+// This callback is invoked when the Speech Recognizer returns.
+// This is where you process the intent and extract the speech text from the intent.
+&#64;Override
+protected void onActivityResult(int requestCode, int resultCode,
+        Intent data) {
+    if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
+        List&lt;String&gt; results = data.getStringArrayListExtra(
+                RecognizerIntent.EXTRA_RESULTS);
+        String spokenText = results.get(0);
+        // Do something with spokenText
+    }
+    super.onActivityResult(requestCode, resultCode, data);
+}
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/wearables/data-layer/accessing.jd b/docs/html/training/wearables/data-layer/accessing.jd
new file mode 100644
index 0000000..4babd0a
--- /dev/null
+++ b/docs/html/training/wearables/data-layer/accessing.jd
@@ -0,0 +1,59 @@
+page.title=Accessing the Wearable Data Layer
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li>Set up a Google Play services client to use the Wearable Data Layer APIs</li>
+</ol>
+
+<h2>Dependencies and Prerequisites</h2>
+<ol>
+  <li><a href="{@docRoot}training/wearables/apps/environment.html">Creating
+  Wearable Apps > Setting up Your Environment</a></li>
+  <li><a href="{@docRoot}training/wearables/apps/creating.html">Creating
+    Wearable Apps > Creating a Project</a></li>
+</ol>
+</div>
+</div>
+
+<p>To call the data layer API, create an instance of
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a>,
+the main entry point for any of the Google Play services APIs.
+</p>
+
+<p>
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a>
+provides a builder that makes it easy to create an instance of the client.
+A minimal <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a> looks like this:
+</p>
+
+<p class="note"><b>Note:</b> For now, this minimal client is enough to get started. However, see
+<a href="{@docRoot}google/auth/api-client.html">Accessing Google Play services APIs</a>
+for more information about creating a<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a>,
+implementing its callbacks, and handling error cases.</p>
+
+<pre style="clear:right">
+GoogleApiClient mGoogleAppiClient = new GoogleApiClient.Builder(this)
+        .addConnectionCallbacks(new ConnectionCallbacks() {
+                &#64;Override
+                public void onConnected(Bundle connectionHint) {
+                    Log.d(TAG, "onConnected: " + connectionHint);
+                }
+                &#64;Override
+                public void onConnectionSuspended(int cause) {
+                    Log.d(TAG, "onConnectionSuspended: " + cause);
+                }
+        })
+        .addOnConnectionFailedListener(new OnConnectionFailedListener() {
+                &#64;Override
+                public void onConnectionFailed(ConnectionResult result) {
+                    Log.d(TAG, "onConnectionFailed: " + result);
+                }
+            })
+        .addApi(Wearable.API)
+        .build();
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/wearables/data-layer/assets.jd b/docs/html/training/wearables/data-layer/assets.jd
new file mode 100644
index 0000000..73ebb73
--- /dev/null
+++ b/docs/html/training/wearables/data-layer/assets.jd
@@ -0,0 +1,123 @@
+page.title=Transferring Assets
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#TransferAsset">Transfer an Asset</a></li>
+  <li><a href="#ReceiveAsset">Receive an Asset</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>
+To send large blobs of binary data over the Bluetooth transport, such as images, attach an
+<a href="{@docRoot}reference/com/google/android/gms/wearable/Asset.html">Asset</a> to a
+data item and the put the data item into the replicated data store.
+</p>
+
+<p>Assets automatically handle caching of data to prevent retransmission and conserve Bluetooth bandwidth.
+A common pattern is for a handheld app to download an image, shrink it to an appropriate size
+for display on the wearable, and transmit it to the wearable app as an Asset. The following examples
+demonstrates this pattern.
+</p>
+
+<p class="note"><b>Note:</b> Although the size of data items are limited to 100KB,
+assets can be as large as desired. However, transferring large assets affect the
+user experience in many cases, so test your apps to ensure that they perform well
+if you're transferring large assets.
+<p>
+
+<h2 id="TransferAsset">Transfer an Asset</h2>
+<p>Create the asset using one of the <code>create...()</code> methods in the
+<a href="{@docRoot}reference/com/google/android/gms/wearable/Asset.html"><code>Asset</code></a> class.
+Here, we convert a bitmap to a byte stream and then call
+<a href="{@docRoot}reference/com/google/android/gms/wearable/Asset.html#createFromBytes(byte[])"><code>createFromBytes()</code></a>
+to create the asset.
+</p>
+
+<pre>
+private static Asset createAssetFromBitmap(Bitmap bitmap) {
+    final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
+    return Asset.createFromBytes(byteStream.toByteArray());
+}
+</pre>
+
+<p>When you have an asset, attach it to a data item with the <code>putAsset()</code> method in
+
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataMap.html"><code>DataMap</code></a>
+or
+<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html"><code>PutDataRequest</code></a>
+and then put the data item into the data store with
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>putDataItem()</code></a>:
+</p>
+
+<p><b>Using PutDataRequest</b></p>
+<pre>
+Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
+Asset asset = createAssetFromBitmap(bitmap);
+PutDataRequest request = PutDataRequest.create("/image");
+request.putAsset("profileImage", asset);
+Wearable.DataApi.putDataItem(mGoogleApiClient, request);
+</pre>
+
+<p><b>Using PutDataMapRequest</b></p>
+<pre>
+Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
+Asset asset = createAssetFromBitmap(bitmap);
+PutDataMapRequest dataMap = PutDataMapRequest.create("/image");
+dataMap.getDataMap().putAsset("profileImage", asset)
+PutDataRequest request = dataMap.asPutDataRequest();
+PendingResult&lt;DataApi.DataItemResult&gt; pendingResult = Wearable.DataApi
+        .putDataItem(mGoogleApiClient, request);
+</pre>
+
+<h2 id="ReceiveAsset">Receive assets</h2>
+
+<p>
+When an asset is created, you probably want to read and extract
+it on other side of the connection. Here's an example of how to implement the
+callback to detect an asset change and extract the Asset:
+</p>
+
+<pre>
+&#64;Override
+public void onDataChanged(DataEventBuffer dataEvents) {
+  for (DataEvent event : dataEvents) {
+    if (event.getType() == DataEvent.TYPE_CHANGED &&
+        event.getDataItem().getUri().getPath().equals("/image")) {
+      BundleDataItem bundleDataItem = BundleDataItem.fromDataItem(dataItem); 
+      Asset profileAsset = bundleDataItem.getData().getParcelable("profileImage");
+      Bitmap bitmap = loadBitmapFromAsset(profileAsset);
+      // Do something with the bitmap
+    }
+  }
+}
+
+public Bitmap loadBitmapFromAsset(Asset asset) {
+    if (asset == null) {
+        throw new IllegalArgumentException("Asset must be non-null");
+    }
+    ConnectionResult result =
+           mGoogleApiClient.blockingConnect(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+    if (!result.isSuccess()) {
+        return null;
+    }
+    // convert asset into a file descriptor and block until it's ready
+    InputStream assetInputStream = Wearable.DataApi.getFdForAsset(
+            mGoogleApiClient, asset).await().getInputStream();
+            mGoogleApiClient.disconnect();
+
+    if (assetInputStream == null) {
+        Log.w(TAG, "Requested an unknown Asset.");
+        return null;
+    }
+    // decode the stream into a bitmap
+    return BitmapFactory.decodeStream(assetInputStream);
+}
+</pre>
diff --git a/docs/html/training/wearables/data-layer/data-items.jd b/docs/html/training/wearables/data-layer/data-items.jd
new file mode 100644
index 0000000..c39e37a
--- /dev/null
+++ b/docs/html/training/wearables/data-layer/data-items.jd
@@ -0,0 +1,124 @@
+page.title=Syncing Data Items
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#SyncData">Sync Data with a Data Map</a></li>
+  <li><a href="#ListenEvents">Listen for Data Item Events</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>
+A <a href="@{docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a>
+defines the data interface that the system uses to synchronize data between handhelds
+and wearables. A <a href="@{docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> generally
+consists of the following items:</p>
+<ul>
+  <li><b>Payload</b> - A byte array, which you can set with whatever data you wish, allowing you
+  to do your own object serialization and deserialization. The size of the payload is limited
+  to 100KB.</li>
+  <li><b>Path</b> - A unique string that must start with a forward slash (for instance,
+  <code>"/path/to/data"</code>)</li>
+</ul>
+
+<p>
+You normally don't implement <a href="@{docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a>
+directly. Instead, you:
+
+<ol>
+  <li>Create a <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html"><code>PutDataRequest</code></a> object,
+  specifying a string path to uniquely identify the item.
+  </li>
+  <li>Call <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])">setData()</a> to set
+  the payload.
+  </li>
+  <li>Call <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>DataApi.putDataItem()</code></a> to request the system to create the data item.
+  </li>
+  <li>When requesting data items, the system returns objects
+  that properly implement the <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a> interface.
+  </li>
+</ol>
+
+<p>
+However, instead of working with raw bytes using <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])">setData()</a>,
+we recommend you <a href="#data-map">use a data map</a>, which exposes
+a data item in an easy-to-use {@link android.os.Bundle}-like interface.
+</p>
+
+<h2 id="SyncData">Sync Data with a Data Map</h2>
+<p>
+When possible, use the <a href="{@docRoot}reference/com/google/android/gms/wearable/DataMap.html"><code>DataMap</code></a> class,
+which lets you work with data items in the form of an Android {@link android.os.Bundle},
+so object serialization and de-serialization is done for you, and you can manipulate data with key-value pairs.
+</p>
+
+<p>To use a data map:</p>
+
+<ol>
+  <li>Create a
+<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html"><code>PutDataMapRequest</code></a>
+object, setting the path of the data item.
+<p class="note"><b>Note:</b> The path string is a unique identifier for the
+data item that allows you to access it from either side of the connection. The path must begin
+with a forward slash. If you're using hierarchical data in your
+app, you should create a path scheme that matches the structure of the data. 
+</p>
+</li>
+<li>Call
+<a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html#getDataMap()"><code>PutDataMapRequest.getDataMap()</code></a>
+</a> to obtain a data map that you can set values on.</li>
+  <li>Set any desired values for the data map using the <code>put...()</code> methods, such as
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/DataMap.html#putString(java.lang.String, java.lang.String)"><code>putString()</code></a>.
+  </li>
+  <li>Call <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataMapRequest.html#asPutDataRequest()"><code>PutDataMapRequest.asPutDataRequest()</code></a>
+  to obtain a <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html"><code>PutDataRequest</code></a> object.
+   </li>
+  <li>Call <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>DataApi.putDataItem()</code></a> to request the system to create the data item.
+  <p class="note"><b>Note:</b>
+  If the handset and wearable devices are disconnected,
+  the data is buffered and and synced when the connection is re-established.
+  </p>
+  </li>
+</ol>
+
+<p>The following example shows how to create a data map, set data on it, and create it:</p>
+
+<pre>
+PutDataMapRequest dataMap = PutDataMapRequest.create("/count");
+dataMap.getDataMap().putInt(COUNT_KEY, count++);
+PutDataRequest request = dataMap.asPutDataRequest();
+PendingResult&lt;DataApi.DataItemResult&gt; pendingResult = Wearable.DataApi
+        .putDataItem(mGoogleApiClient, request);
+</pre>
+
+<h2 id="ListenEvents">Listen for Data Item Events</h2>
+If one side of the data layer connection changes a data item, you probably want
+to be notified of any changes on the other side of the connection.
+You can do this by implementing a listener for data item events.
+
+<p>For example, here's what a typical callback looks like to carry out certain actions
+when data changes.</p>
+
+<pre>
+&#64;Override
+public void onDataChanged(DataEventBuffer dataEvents) {
+    for (DataEvent event : dataEvents) {
+        if (event.getType() == DataEvent.TYPE_DELETED) {
+            Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
+        } else if (event.getType() == DataEvent.TYPE_CHANGED) {
+             Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
+        }
+    }
+}
+</pre>
+<p>
+This is just a snippet that requires more implementation details. Learn about
+how to implement a full listener service or activity in
+<a href="{@docRoot}training/wearables/data-layer/listeners.html">Listening for Data Layer Events</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/training/wearables/data-layer/events.jd b/docs/html/training/wearables/data-layer/events.jd
new file mode 100644
index 0000000..0146c4e
--- /dev/null
+++ b/docs/html/training/wearables/data-layer/events.jd
@@ -0,0 +1,312 @@
+page.title=Handling Data Layer Events
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#Wait">Wait for the Status of Data Layer Calls</a></li>
+  <li><a href="#Listen">Listen for Data Layer Events</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>When you make calls with the data layer, you can receive the status
+of the call when it completes as well as listen for any changes that
+the call ends up making with listeners.
+</p>
+
+<h2 id="Wait">Wait for the Status of Data Layer Calls</h2>
+
+<p>You'll notice that calls to the data layer API sometimes return a
+<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>,
+such as
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>putDataItem()</code></a>.
+As soon as the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> is created,
+the operation is queued in the background. If you do nothing else after this, the operation
+eventually completes silently. However, you'll usually want to do something with the result
+after the operation completes, so the
+<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
+lets you wait for the result status, either synchronously or asynchronously.
+</p>
+
+<h3 id="async-waiting">Asynchronously waiting</h3>
+<p>If your code is running on the main UI thread, do not making blocking calls
+to the data layer API. You can run the calls asynchronously by adding a callback
+to the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> object,
+which fires when the operation is completed:</p>
+<pre>
+pendingResult.setResultCallback(new ResultCallback&lt;DataItemResult&gt;() {
+    &#64;Override
+    public void onResult(final DataItemResult result) {
+        if(result.getStatus().isSuccess()) {
+        Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
+    }
+});
+</pre>
+
+<h3 id="sync-waiting">Synchronously waiting</h3>
+<p>If your code is running on a separate handler thread in a background service (which is the case
+in a <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>),
+it's fine for the calls to block. In this case, you can call
+<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#await()"><code>await()</code></a>
+on the PendingResult object, which will block until the request has completed, and return a Result
+object:
+</p>
+
+<pre>
+DataItemResult result = pendingResult.await();
+if(result.getStatus().isSuccess()) {
+    Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
+}
+</pre>
+
+
+<h2 id="Listen">Listen for Data Layer Events </h2>
+<p>Because the data layer synchronizes and sends data across the handheld and
+wearable, you normally want to listen for important events, such as when data items
+are created, messages are received, or when the wearable and handset are connected.
+</p>
+<p>To listen for data layer events, you have two options:</p>
+
+<ul>
+  <li>Create a service that extends
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>.
+  </li>
+  <li>Create an activity that implements
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a>.
+  </li>
+</ul>
+
+<p>With both these options, you override any of the data event callbacks that you care about
+handling in your implementation.</p>
+
+<h3 id="listener-service">With a WearableListenerService</h3>
+
+<p>
+You typically create instances of this service in both your wearable and handheld apps. If you
+don't care about data events in one of these apps, then you don't need to implement this
+service in that particular app.</p>
+
+<p>For example, you can have a handheld app that sets and gets data item objects and a wearable app
+that listens for these updates to update it's UI. The wearable never updates any of the data items,
+so the handheld app doesn't listen for any data events from the wearable app.</p>
+
+<p>You can listen for the following events with
+<a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>:</p>
+
+<ul>
+  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)"><code>onDataChanged()</code></a>
+- Called when data item objects are created, changed, or deleted. An event on one side of a connection
+triggers an this callback on both sides.</li>
+  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onMessageReceived(com.google.android.gms.wearable.MessageEvent)"><code>onMessageReceived()</code></a>
+-  A message sent from one side of a connection triggers this callback on the other side of the connection.</li>
+  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onMessageReceived(com.google.android.gms.wearable.MessageEvent)"><code>onPeerConnected()</code></a>
+  and <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onPeerDisconnected(com.google.android.gms.wearable.Node)"><code>onPeerDisconnected()</code></a> -
+  Called when connection with the handheld or wearable is connected or disconnected. 
+  Changes in connection state on one side of the connection triggers these callbacks on both sides of the connection.
+  </li>
+</ul>
+
+<p>To create a <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>:</p>
+
+<ol>
+  <li>Create a class that extends
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>.
+  </li>
+  <li>Listen for the events that you care about, such as
+  <a href="{@docRoot}/reference/com/google/android/gms/wearable/WearableListenerService.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)"><code>onDataChanged()</code></a>.
+  </li>
+  <li>Declare an intent filter in your Android manifest to notify the system about your
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>.
+  This allows the system to bind your service as needed.
+  </li>
+</ol>
+
+  <p>The following example shows how to implement a simple
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>:
+  </p>
+
+<pre>
+public class DataLayerListenerService extends WearableListenerService {
+
+    private static final String TAG = "DataLayerSample";
+    private static final String START_ACTIVITY_PATH = "/start-activity";
+    private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";
+
+    &#64;Override
+    public void onDataChanged(DataEventBuffer dataEvents) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "onDataChanged: " + dataEvents);
+        }
+        final List<DataEvent> events = FreezableUtils
+                .freezeIterable(dataEvents);
+
+        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
+                .addApi(Wearable.API)
+                .build();
+
+        ConnectionResult connectionResult =
+                googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
+
+        if (!connectionResult.isSuccess()) {
+            Log.e(TAG, "Failed to connect to GoogleApiClient.");
+            return;
+        }
+
+        // Loop through the events and send a message
+        / to the node that created the data item.
+        for (DataEvent event : events) {
+            Uri uri = event.getDataItem().getUri();
+
+            // Get the node id from the host value of the URI
+            String nodeId = uri.getHost();
+            // Set the data of the message to be the bytes of the URI.
+            byte[] payload = uri.toString().getBytes();
+
+            // Send the RPC
+            Wearable.MessageApi.sendMessage(googleApiClient, nodeId,
+                    DATA_ITEM_RECEIVED_PATH, payload);
+        }
+    }
+}
+</pre>  
+
+<p>Here's the corresponding intent filter in the Android manifest file:</p>
+
+<pre>
+&lt;service android:name=".DataLayerListenerService"&gt;
+  &lt;intent-filter&gt;
+      &lt;action android:name="com.google.android.gms.wearable.BIND_LISTENER" /&gt;
+  &lt;/intent-filter&gt;
+&lt;/service&gt;
+</pre>
+
+
+<h4>Permissions within Data Layer Callbacks</h4>
+
+<p>In order to deliver callbacks to your application for data layer events, Google Play services
+binds to your <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>,
+and calls your callbacks via IPC. This has the consequence
+that your callbacks inherit the permissions of the calling process.</p>
+
+<p>If you try to perform a privileged operation within a callback, the security check fails because your callback is
+running with the identity of the calling process, instead of the identity of your app's
+process.</p>
+
+<p>To fix this, call {@link android.os.Binder#clearCallingIdentity} </a>,
+to reset identity after crossing the IPC boundary, and then restore identity with
+{@link android.os.Binder#restoreCallingIdentity restoreCallingIdentity()} when
+you've completed the privileged operation:
+</p>
+
+<pre>
+long token = Binder.clearCallingIdentity();
+try {
+    performOperationRequiringPermissions();
+} finally {
+    Binder.restoreCallingIdentity(token);
+}
+</pre>
+
+<h3 id="Listen">With a Listener Activity</h3>
+
+<p>
+If your app only cares about data layer events when the user is interacting
+with the app and does not need a long-running service to handle every data
+change, you can listen for events in an activity by implementing one or more
+of the following interfaces:
+
+<ul>
+  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a></li>
+  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.MessageListener.html"><code>MessageApi.MessageListener</code></a></li>
+  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.NodeListener.html"><code>NodeApi.NodeListener</code></a></li>
+</ul>
+</p>
+
+<p>To create an activity that listens for data events:</p>
+<ol>
+<li>Implement the desired interfaces.</li>
+<li>In {@link android.app.Activity#onCreate}, create an instance of
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code></a>
+to work with the data layer API.
+<li>
+In {@link android.app.Activity#onStart onStart()}, call <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"><code>connect()</code></a> to connect the client to Google Play services.
+</li>
+<li>When the connection to Google Play services is established, the system calls
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>. This is where you call
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)"><code>DataApi.addListener()</code></a>,
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"><code>MessageApi.addListener()</code></a>,
+  or <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.NodeApi.NodeListener)"><code>NodeApi.addListener()</code></a>
+  to notify Google Play services that your activity is interested in listening for data layer events.
+</li>
+<li>In {@link android.app.Activity#onStop onStop()}, unregister any listeners with
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)"><code>DataApi.removeListener()</code></a>,
+<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"><code>MessageApi.removeListener()</code></a>,
+or <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.NodeApi.NodeListener)"><code>NodeApi.removeListener()</code></a>.
+</li>
+<li>Implement <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)"><code>onDataChanged()</code>,
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.NodeListener.html#onPeerConnected(com.google.android.gms.wearable.Node)"><code>onMessageReceived()</code></a>,
+    <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.NodeListener.html#onPeerConnected(com.google.android.gms.wearable.Node)"><code>onPeerConnected()</code></a>, and
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.NodeListener.html#onPeerDisconnected(com.google.android.gms.wearable.Node)"><code>onPeerDisconnected()</code></a>, depending on the interfaces that you implemented.
+</li>
+</ol>
+
+<p>Here's an example that implements
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a>:</p>
+
+<pre>
+public class MainActivity extends Activity implements
+        DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.main);
+        mGoogleApiClient = new GoogleApiClient.Builder(this)
+                .addApi(Wearable.API)
+                .addConnectionCallbacks(this)
+                .addOnConnectionFailedListener(this)
+                .build();
+    }
+
+    &#64;Override
+    protected void onStart() {
+        super.onStart();
+        if (!mResolvingError) {
+            mGoogleApiClient.connect();
+        }
+    }
+
+   &#64;Override
+    public void onConnected(Bundle connectionHint) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "Connected to Google Api Service");
+        }
+        Wearable.DataApi.addListener(mGoogleApiClient, this);
+    }
+
+    &#64;Override
+    protected void onStop() {
+        if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
+            Wearable.NodeApi.removeListener(mGoogleApiClient, this);
+            mGoogleApiClient.disconnect();
+        }
+        super.onStop();
+    }
+
+    &#64;Override
+    public void onDataChanged(DataEventBuffer dataEvents) {
+        for (DataEvent event : dataEvents) {
+            if (event.getType() == DataEvent.TYPE_DELETED) {
+                Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
+            } else if (event.getType() == DataEvent.TYPE_CHANGED) {
+                 Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
+            }
+        }
+    }
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/wearables/data-layer/index.jd b/docs/html/training/wearables/data-layer/index.jd
new file mode 100644
index 0000000..3e06df1
--- /dev/null
+++ b/docs/html/training/wearables/data-layer/index.jd
@@ -0,0 +1,87 @@
+page.title=Sending and Syncing Data
+@jd:body
+
+<div id="tb-wrapper">
+  <div id="tb">
+
+    <!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+    <h2>Dependencies and prerequisites</h2>
+    <ul>
+      <li>Android 4.3 (API Level 18) or higher on the handset device</li>
+      <li>The latest version of <a href="{@docRoot}google/play">Google Play services</a></li>
+      <li>An Android Wear device or Wear AVD</li>
+    </ul>
+  </div>
+</div>
+
+<p>
+The Wearable Data Layer API, which is part of Google Play services, provides a communication channel
+for your handheld and wearable apps. The API consists of a set of data objects that the system can
+send and synchronize over the wire and listeners that notify your apps of important events with
+the data layer:</p>
+
+<dl>
+  <dt><b>Data Items</b></dt>
+  <dd>A <a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a>
+  provides data storage with automatic syncing between the handheld and
+  wearable.</dd>
+
+  <dt><b>Messages</b></dt>
+  <dd>The <a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html"><code>MessageApi</code></a> class
+  can send messages designed for "fire-and-forget" commands, such as controlling a handheld's
+  media player from the wearable or starting an intent on the wearable from the handheld.
+  The system always delivers the message when the handheld and wearable are connected and delivers
+  an error when the devices are disconnected. Messages are great for one-way requests or for a
+  request/response communication model.</dd>
+
+  <dt><b>Asset</b></dt>
+  <dd><a href="{@docRoot}reference/com/google/android/gms/wearable/Asset.html"><code>Asset</code></a> objects are for
+  sending binary blobs of data, such as images. You attach assets to data items and the system
+  automatically takes care of the transfer for you, conserving Bluetooth bandwidth by caching large assets
+  to avoid re-transmission.</dd>
+
+  <dt><b>WearableListenerService</b> (for services)</dt>
+  <dd><p>Extending <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>
+  lets you listen for important data layer events in a service. The system manages the lifecycle of
+  the <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>,
+  binding to the service when it needs to send data items or messages and unbinding the service when no work is needed.</p>
+  </dd>
+
+  <dt><b>DataListener</b> (for foreground activities)</dt>
+  <dd>
+  Implementing <a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataListener</code></a>
+  in an activity lets you listen for important data layer events when an activity
+  is in the foreground. Using this instead of the
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>
+  lets you listen for changes only when the user is actively using your app.
+  </dd>
+</dl>
+
+<p class="warning"><b>Warning:</b>
+Because these APIs are designed for communication between handhelds and wearables,
+these are the only APIs you should use to set up communication between these
+devices. For instance, don't try to open low-level sockets to create a communication
+channel.
+</p>
+
+<h2>Lessons</h2>
+  <dl>
+    <dt><a href="{@docRoot}training/wearables/data-layer/data-items.html">Accessing the Wearable Data Layer</a></dt>
+    <dd>This lesson shows you how to create a client to access the Data Layer APIs.</dd>
+
+    <dt><a href="{@docRoot}training/wearables/data-layer/data-items.html">Syncing Data Items</a></dt>
+    <dd>Data items are objects that are stored in a replicated data store that is automatically
+      synced from handhelds to wearables.</dd>
+
+    <dt><a href="{@docRoot}training/wearables/data-layer/assets.html">Transferring Assets</a></dt>
+      <dd>Assets are binary blobs of data that you typically use to transfer images or media.</dd>
+
+    <dt><a href="{@docRoot}training/wearables/data-layer/stacks.html">Sending and Receiving Messages</a></dt>
+      <dd>Messages are designed for fire-and-forget messages that you can send back and forth
+      between the wearable and handheld.</dd>
+
+    <dt><a href="{@docRoot}training/wearables/data-layer/events.html">Handling Data Layer Events</a></dt>
+      <dd>Be notified of changes and events to the data layer.</dd>
+  </dl>
+
+</div>
\ No newline at end of file
diff --git a/docs/html/training/wearables/data-layer/messages.jd b/docs/html/training/wearables/data-layer/messages.jd
new file mode 100644
index 0000000..a9dec75
--- /dev/null
+++ b/docs/html/training/wearables/data-layer/messages.jd
@@ -0,0 +1,99 @@
+page.title=Sending and Receiving Messages
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#SendMessage">Send a Message</a></li>
+  <li><a href="#ReceiveMessage">Receive a Message</a></li>
+</ol>
+</div>
+</div>
+
+<p>You send messages using the
+<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html"><code>MessageApi</code></a>
+and attach the following items to the message:</p>
+
+<ul>
+  <li>An arbitrary payload (optional)</li>
+  <li>A path that uniquely identifies the message's action</li>
+</ul>
+<p>
+Unlike data items, there is no syncing between the handheld and wearable apps.
+Messages are a one-way communication mechanism that's meant for
+"fire-and-forget" tasks, such as sending a message to the wearable
+to start an activity. You can also use messages in request/response model
+where one side of the connection sends a message, does some work,
+sends back a response message.</p>
+
+<h2 id="SendMessage">Send a Message</h2>
+
+<p>The following example shows how to send a message that indicates to the other
+side of the connect to start an activity.
+This call is made synchronously, which blocks until the message
+is received or when the request times out:
+</p>
+
+<p class="note"><b>Note:</b> Read more about asynchronous and synchronous calls
+to Google Play services and when to use each in
+<a href="google/auth/api-client.html#Communicating">Communicate with Google Play Services</a>.
+</p>
+
+<pre>
+Node node; // the connected device to send the message to
+GoogleApiClient mGoogleApiClient;
+public static final START_ACTIVITY_PATH = "/start/MainActivity";
+...
+
+    SendMessageResult result = Wearable.MessageApi.sendMessage(
+            mGoogleApiClient, node, START_ACTIVITY_PATH, null).await();
+    if (!result.getStatus().isSuccess()) {
+        Log.e(TAG, "ERROR: failed to send Message: " + result.getStatus());
+    }
+</pre>
+
+<p>
+Here's a simple way to get a list of connected nodes that you can potentially
+send messages to:</p>
+
+<pre>
+private Collection&lt;String&gt; getNodes() {
+    HashSet &lt;String&gt;results= new HashSet&lt;String&gt;();
+    NodeApi.GetConnectedNodesResult nodes =
+            Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
+    for (Node node : nodes.getNodes()) {
+        results.add(node.getId());
+    }
+    return results;
+}
+</pre>
+
+<h2 id="ReceiveMessage">Receiving a Message</h2>
+
+<p>
+
+To be notified of received messages, you implement a listener for message events.
+This example shows how you might do this by checking the <code>START_ACTIVITY_PATH</code>
+that the previous example used to send the message. If this condition is <code>true</code>,
+a specific activity is started.
+</p>
+
+<pre>
+&#64;Override
+public void onMessageReceived(MessageEvent messageEvent) {
+    if (messageEvent.getPath().equals(START_ACTIVITY_PATH)) {
+        Intent startIntent = new Intent(this, MainActivity.class);
+        startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        startActivity(startIntent);
+    }
+}
+</pre>
+
+<p>
+This is just a snippet that requires more implementation details. Learn about
+how to implement a full listener service or activity in
+<a href="#listening">Listening for Data Layer Events</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/training/wearables/notifications/creating.jd b/docs/html/training/wearables/notifications/creating.jd
new file mode 100644
index 0000000..a61fa07
--- /dev/null
+++ b/docs/html/training/wearables/notifications/creating.jd
@@ -0,0 +1,295 @@
+page.title=Creating a Notification
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#Import">Import the Necessary Classes</a></li>
+  <li><a href="#NotificationBuilder">Create Notifications with the Notification Builder</a></li>
+  <li><a href="#ActionButtons">Add Action Buttons</a></li>
+  <li><a href="#SpecifyWearableOnlyActions">Specify Wearable-only Actions</a></li>
+  <li><a href="#BigView">Add a Big View</a></li>
+  <li><a href="#AddWearableFeatures">Add Wearable Features for a Notification</a></li>
+  <li><a href="#Deliver">Deliver the Notification</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>To build handheld notifications that are also sent to wearables, use
+{@link android.support.v4.app.NotificationCompat.Builder}. When you build
+notifications with this class, the system takes care of displaying
+notifications properly, whether they appear on a handheld or wearable.
+</p>
+
+<p class="note"><strong>Note:</strong>
+Notifications using {@link android.widget.RemoteViews} are stripped of custom
+layouts and the wearable only displays the text and icons. However, you can create
+<a href="{@docRoot}training/wearables/apps/layouts.html#CustomNotifications">create custom notifications</a>
+that use custom card layouts by creating a wearable app that runs on the wearable device.</p>
+</div>
+
+<h2 id="Import">Import the necessary classes</h2>
+<p>Before you begin, import the necessary classes from the support library:</p>
+
+<pre style="clear:right">
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.v4.app.NotificationCompat.WearableExtender;
+</pre>
+
+<h2 id="NotificationBuilder">Create Notifications with the Notification Builder</h2>
+
+<p>The <a href="http://developer.android.com/tools/support-library/features.html#v4">v4
+support library</a> allows you to create notifications using the latest notification features
+such as action buttons and large icons, while remaining compatible with Android 1.6 (API level
+4) and higher.</p>
+
+<p>To create a notification with the support library, you create an instance of
+{@link android.support.v4.app.NotificationCompat.Builder} and issue the notification by
+passing it to {@link android.support.v4.app.NotificationManagerCompat#notify notify()}. For example:
+</p>
+
+<pre>
+int notificationId = 001;
+// Build intent for notification content
+Intent viewIntent = new Intent(this, ViewEventActivity.class);
+viewIntent.putExtra(EXTRA_EVENT_ID, eventId);
+PendingIntent viewPendingIntent =
+        PendingIntent.getActivity(this, 0, viewIntent, 0);
+
+NotificationCompat.Builder notificationBuilder =
+        new NotificationCompat.Builder(this)
+        .setSmallIcon(R.drawable.ic_event)
+        .setContentTitle(eventTitle)
+        .setContentText(eventLocation)
+        .setContentIntent(viewPendingIntent);
+
+// Get an instance of the NotificationManager service
+NotificationManagerCompat notificationManager =
+        NotificationManagerCompat.from(this);
+
+// Build the notification and issues it with notification manager.
+notificationManager.notify(notificationId, notificationBuilder.build());
+</pre>
+
+<p>When this notification appears on a handheld device, the user can invoke the
+{@link android.app.PendingIntent}
+specified by the {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+setContentIntent()} method by touching the notification. When this
+notification appears on an Android wearable, the user can swipe the notification to the left to
+reveal the <strong>Open</strong> action, which invokes the intent on the handheld device.</p>
+
+
+<img src="{@docRoot}wear/images/circle_email_action.png" height="200"
+  style="float:right;clear:right;margin:0 0 20px 60px" />
+
+<h2 id="ActionButtons">Add Action Buttons</h2>
+
+<p>In addition to the primary content action defined by
+{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+setContentIntent()}, you can add other actions by passing a {@link android.app.PendingIntent} to
+the {@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} method.</p>
+
+<p>For example, the following code shows the same type of notification from above, but adds an
+action to view the event location on a map.</p>
+
+<pre style="clear:right">
+// Build an intent for an action to view a map
+Intent mapIntent = new Intent(Intent.ACTION_VIEW);
+Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));
+mapIntent.setData(geoUri);
+PendingIntent mapPendingIntent =
+        PendingIntent.getActivity(this, 0, mapIntent, 0);
+
+NotificationCompat.Builder notificationBuilder =
+        new NotificationCompat.Builder(this)
+        .setSmallIcon(R.drawable.ic_event)
+        .setContentTitle(eventTitle)
+        .setContentText(eventLocation)
+        .setContentIntent(viewPendingIntent)
+        <b>.addAction(R.drawable.ic_map,
+                getString(R.string.map), mapPendingIntent);</b>
+</pre>
+
+<p>On a handheld, the action appears as an
+additional button attached to the notification. On a wearable, the action appears as
+a large button when the user swipes the notification to the left. When the user taps the action,
+the associated intent is invoked on the handheld.</p>
+
+<p class="note"><strong>Tip:</strong> If your notifications include a "Reply" action
+  (such as for a messaging app), you can enhance the behavior by enabling
+  voice input replies directly from the Android wearable. For more information, read
+  <a href="{@docRoot}training/wearables/notifications/voice-input.html">Receiving Voice Input from
+  a Notification</a>.
+</p>
+
+<h2 id="SpecifyWearableOnlyActions">Specify Wearable-only Actions</h2>
+
+<p>
+If you want the actions available on the wearable to be different from those on the handheld,
+then use {@link android.support.v4.app.NotificationCompat.WearableExtender#addAction WearableExtender.addAction()}.
+Once you add an action with this method, the wearable does not display any other actions added with
+{@link android.support.v4.app.NotificationCompat.Builder#addAction NotificationCompat.Builder.addAction()}.
+That is, only the actions added with {@link android.support.v4.app.NotificationCompat.WearableExtender#addAction WearableExtender.addAction()} appear on the wearable and they do not appear on the handheld.
+</p>
+
+<pre>
+// Create an intent for the reply action
+Intent actionIntent = new Intent(this, ActionActivity.class);
+PendingIntent actionPendingIntent =
+        PendingIntent.getActivity(this, 0, actionIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+// Create the action
+NotificationCompat.Action action =
+        new NotificationCompat.Action.Builder(R.drawable.ic_action,
+                getString(R.string.label, actionPendingIntent))
+                .build();
+
+// Build the notification and add the action via WearableExtender
+Notification notification =
+        new NotificationCompat.Builder(mContext)
+                .setSmallIcon(R.drawable.ic_message)
+                .setContentTitle(getString(R.string.title))
+                .setContentText(getString(R.string.content))
+                .extend(new WearableExtender().addAction(action))
+                .build();
+</pre>
+<h2 id="BigView">Add a Big View</h2>
+
+<img src="{@docRoot}wear/images/06_images.png" height="200"
+  style="float:right;margin:0 0 20px 40px" />
+
+<p>You can insert extended text content
+to your notification by adding one of the "big view" styles to your notification. On a
+handheld device, users can see the big view content by expanding the notification. On
+a wearable device, the big view content is visible by default.</p>
+
+<p>To add the extended content to your notification, call {@link
+android.support.v4.app.NotificationCompat.Builder#setStyle setStyle()} on the {@link
+android.support.v4.app.NotificationCompat.Builder} object, passing it an instance of either
+{@link android.support.v4.app.NotificationCompat.BigTextStyle BigTextStyle} or
+{@link android.support.v4.app.NotificationCompat.InboxStyle InboxStyle}.</p>
+
+<p>For example, the following code adds an instance of
+{@link android.support.v4.app.NotificationCompat.BigTextStyle} to the event notification,
+in order to include the complete event description (which includes more text than can fit
+into the space provided for {@link android.support.v4.app.NotificationCompat.Builder#setContentText
+setContentText()}).</p>
+
+<pre style="clear:right">
+// Specify the 'big view' content to display the long
+// event description that may not fit the normal content text.
+BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
+bigStyle.bigText(eventDescription);
+
+NotificationCompat.Builder notificationBuilder =
+        new NotificationCompat.Builder(this)
+        .setSmallIcon(R.drawable.ic_event)
+        .setLargeIcon(BitmapFractory.decodeResource(
+                getResources(), R.drawable.notif_background))
+        .setContentTitle(eventTitle)
+        .setContentText(eventLocation)
+        .setContentIntent(viewPendingIntent)
+        .addAction(R.drawable.ic_map,
+                getString(R.string.map), mapPendingIntent)
+        <b>.setStyle(bigStyle);</b>
+</pre>
+
+<p>Notice that you can add a large background image to any notification using the
+{@link android.support.v4.app.NotificationCompat.Builder#setLargeIcon setLargeIcon()}
+method. For more information about designing notifications with large images, see the
+<a href="{@docRoot}design/wear/index.html">Design Principles of Android
+Wear</a>.</p>
+
+<h2 id="AddWearableFeatures">Add Wearable Features For a Notification</h2>
+
+<p>If you ever need to add wearable-specific options to a notification, such as specifying additional
+pages of content or letting users dictate a text response with voice input, you can use the
+{@link android.support.v4.app.NotificationCompat.WearableExtender} class to
+specify the options. To use this API:</p>
+
+<ol>
+  <li>Create an instance of a {@link android.support.v4.app.NotificationCompat.WearableExtender WearableExtender},
+  setting the wearable-specific options for the notication.</li>
+  <li>Create an instance of
+  {@link android.support.v4.app.NotificationCompat.Builder}, setting the
+  desired properties for your notification as described earlier in this lesson.</li>
+  <li>Call {@link android.support.v4.app.NotificationCompat.Builder#extend extend()} on
+  the notification and pass in the
+  {@link android.support.v4.app.NotificationCompat.WearableExtender WearableExtender}. This applies
+  the wearable options to the notification.</li>
+  <li>Call {@link android.support.v4.app.NotificationCompat.Builder#build} to build the notification.</li>
+</ol>
+
+<p>
+For example, the following code calls the
+{@link android.support.v4.app.NotificationCompat.WearableExtender#setHintHideIcon setHintHideIcon()}
+method to remove the app icon from the notification card.
+</p>
+
+<pre>
+// Create a WearableExtender to add functionality for wearables
+NotificationCompat.WearableExtender wearableExtender =
+        new NotificationCompat.WearableExtender()
+        .setHintHideIcon(true);
+
+// Create a NotificationCompat.Builder to build a standard notification
+// then extend it with the WearableExtender
+Notification notif = new NotificationCompat.Builder(mContext)
+        .setContentTitle("New mail from " + sender)
+        .setContentText(subject)
+        .setSmallIcon(R.drawable.new_mail);
+        .extend(wearableExtender)
+        .build();
+</pre>
+
+<p>The
+  {@link android.support.v4.app.NotificationCompat.WearableExtender#setHintHideIcon setHintHideIcon()}
+  method is just one example of new notification features available with
+  {@link android.support.v4.app.NotificationCompat.WearableExtender}.
+</p>
+
+<p>If you ever need to read wearable-specifc options at a later time, use the corresponding get
+method for the option. This example calls the
+{@link android.support.v4.app.NotificationCompat.WearableExtender#getHintHideIcon()} method to
+get whether or not this notification hides the icon:
+<pre>
+NotificationCompat.WearableExtender wearableExtender =
+        new NotificationCompat.WearableExtender(notif);
+boolean hintHideIcon = wearableExtender.getHintHideIcon();
+</pre>
+
+<h2 id="Deliver">Deliver the Notification</h2>
+<p>When you want to deliver your notifications, always use the
+  {@link android.support.v4.app.NotificationManagerCompat} API instead of
+  {@link android.app.NotificationManager}:</p>
+
+<pre>
+// Get an instance of the NotificationManager service
+NotificationManagerCompat notificationManager =
+        NotificationManagerCompat.from(mContext);
+
+// Issue the notification with notification manager.
+notificationManager.notify(notificationId, notif);
+</pre>
+
+<p>If you use the framework's {@link android.app.NotificationManager}, some
+features from {@link android.support.v4.app.NotificationCompat.WearableExtender}
+do not work, so make sure to use {@link android.support.v4.app.NotificationCompat}.
+</p>
+
+<pre>
+NotificationCompat.WearableExtender wearableExtender =
+        new NotificationCompat.WearableExtender(notif);
+boolean hintHideIcon = wearableExtender.getHintHideIcon();
+ </pre>
+
+<p>The {@link android.support.v4.app.NotificationCompat.WearableExtender} APIs allow you to add
+additional pages to notifications, stack notifications, and more. Continue to the following lessons
+to learn about these features.
+</p>
\ No newline at end of file
diff --git a/docs/html/training/wearables/notifications/index.jd b/docs/html/training/wearables/notifications/index.jd
new file mode 100644
index 0000000..17f3cb3
--- /dev/null
+++ b/docs/html/training/wearables/notifications/index.jd
@@ -0,0 +1,51 @@
+page.title=Adding Wearable Features to Notifications
+@jd:body
+
+<div id="tb-wrapper">
+  <div id="tb">
+
+    <h2>Dependencies and prerequisites</h2>
+    <ul>
+      <li>Android 4.3 (API Level 18) or higher on the handset device</li>
+      <li>An Android Wear device or Wear AVD</li>
+      <li><a href="{@docRoot}tools/support-library/features.html#v4">The Android v4 support library
+      (or v13, which includes v4)</li>
+    </ul>
+    <h2>You should also read</h2>
+    <ul>
+      <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li>
+    </ul>
+  </div>
+</div>
+
+<p>When an Android handheld (phone or tablet) and Android wearable are connected, the handheld
+automatically shares notifications with the wearable. On the wearable, each
+notification appears as a new card in the <a href="{@docRoot}design/wear/index.html"
+>context stream</a>.</p>
+
+<p>However, to give users the best experience, you should add wearable-specific functionality to the
+notifications you already create. The following lessons show you how to
+create notifications that are catered for handhelds and wearables at the same time.
+</p>
+
+<img src="{@docRoot}wear/images/notification_phone@2x.png" width="700" height="265" />
+
+<p class="caption"><b>Figure 1.</b> The same notification displayed on a handheld and wearable.</p>
+
+<h2>Lessons</h2>
+  <dl>
+    <dt><a href="{@docRoot}training/wearables/notifications/creating.html">Creating a notification</a></dt>
+      <dd>Learn how to create notifications with wearable features with the Android support library.</dd>
+    <dt><a href="{@docRoot}training/wearables/notifications/voice-input.html">Receiving Voice Input
+in a Notification</a></dt>
+      <dd>Learn how to add an action to a wearable notification that receives voice input from users and delivers
+      the transcribed message to your handset app.</dd>
+    <dt><a href="{@docRoot}training/wearables/notifications/pages.html">Adding Pages to a Notification</a></dt>
+      <dd>Learn how to add additional pages of information that are visible when the user
+swipes to the left.</dd>
+    <dt><a href="{@docRoot}training/wearables/notifications/stacks.html">Stacking Notifications</a></dt>
+      <dd>Learn how to place all similar notifications from your app in a stack, allowing users to view
+      each notification individually without adding multiple cards to the card stream.</dd>
+  </dl>
+
+</div>
\ No newline at end of file
diff --git a/docs/html/training/wearables/notifications/pages.jd b/docs/html/training/wearables/notifications/pages.jd
new file mode 100644
index 0000000..d74c8ea
--- /dev/null
+++ b/docs/html/training/wearables/notifications/pages.jd
@@ -0,0 +1,71 @@
+page.title=Adding Pages to a Notification
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li>Add Pages to a Notification</li>
+</ol>
+</div>
+</div>
+
+<p>When you'd like to provide more information without requiring users
+to open your app on their handheld device, you can
+add one or more pages to the notification on the wearable. The additional pages
+appear immediately to the right of the main notification card.
+</p>
+
+<img src="{@docRoot}wear/images/09_pages.png" height="200" style="margin:0 0 20px 0" />
+<img src="{@docRoot}wear/images/08_pages.png" height="200" style="margin:0 0 20px 40px" />
+
+<p>To create a notification with multiple pages:</p>
+<ol>
+    <li>Create the main notification (the first page) with
+    {@link android.support.v4.app.NotificationCompat.Builder},
+    in the way you'd like the notification to appear on a handset.</li>
+    <li>Create the additional pages for the wearable with
+    {@link android.support.v4.app.NotificationCompat.Builder}.</li>
+    <li>Apply the pages to the main notification with the
+    {@link android.support.v4.app.NotificationCompat.WearableExtender#addPage addPage()}
+    method or add multiple pages in a {@link java.util.Collection} with the
+    {@link android.support.v4.app.NotificationCompat.WearableExtender#addPage addPages()} method.
+    </li>
+</ol>
+
+<p>For example, here's some code that adds a second page to a notification:</p>
+
+<pre>
+// Create builder for the main notification
+NotificationCompat.Builder notificationBuilder =
+        new NotificationCompat.Builder(this)
+        .setSmallIcon(R.drawable.new_message)
+        .setContentTitle("Page 1")
+        .setContentText("Short message")
+        .setContentIntent(viewPendingIntent);
+
+// Create a big text style for the second page
+BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
+secondPageStyle.setBigContentTitle("Page 2")
+               .bigText("A lot of text...");
+
+// Create second page notification
+Notification secondPageNotification =
+        new NotificationCompat.Builder(this)
+        .setStyle(secondPageStyle)
+        .build();
+
+// Add second page with wearable extender and extend the main notification
+Notification twoPageNotification =
+        new WearableExtender()
+                .addPage(secondPageNotification)
+                .extend(notificationBuilder)
+                .build();
+
+// Issue the notification
+notificationManager =
+        NotificationManagerCompat.from(this);
+notificationManager.notify(notificationId, twoPageNotification);
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/wearables/notifications/stacks.jd b/docs/html/training/wearables/notifications/stacks.jd
new file mode 100644
index 0000000..e71e74c
--- /dev/null
+++ b/docs/html/training/wearables/notifications/stacks.jd
@@ -0,0 +1,154 @@
+page.title=Stacking Notifications
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#AddGroup">Add Each Notification to a Group</a></li>
+  <li><a href="#AddSummary">Add a Summary Notification</a></li>
+</ol>
+
+</div>
+</div>
+<img src="/wear/images/11_bundles_B.png" height="200" width="169"
+    style="margin:0 0 20px 20px; clear:both; float:right" alt="">
+<img src="/wear/images/11_bundles_A.png" height="200" width="169"
+    style="margin:0 20px 20px 20px; float:right" alt="">
+<p>When creating notifications for a handheld device, you should always aggregate similar
+notifications into a single summary notification. For example, if your app creates notifications
+for received messages, you should not show more than one notification
+on a handheld device&mdash;when more than one is message is received, use a single notification
+to provide a summary such as "2 new messages."</p>
+
+<p>However, a summary notification is less useful on an Android wearable because users
+are not able to read details from each message on the wearable (they must open your app on the
+handheld to view more information). So for the wearable device, you should
+group all the notifications together in a stack. The stack of notifications appears as a single
+card, which users can expand to view the details from each notification separately. The new
+{@link android.support.v4.app.NotificationCompat.Builder#setGroup setGroup()} method makes this
+possible while allowing you to still provide only one summary notification on the handheld device.</p>
+
+<h2 id="AddGroup" style="clear:right">Add Each Notification to a Group</h2>
+
+<p>To create a stack, call {@link android.support.v4.app.NotificationCompat.Builder#setGroup setGroup()}
+for each notification you want in the stack and specify a
+group key. Then call {@link android.support.v4.app.NotificationManagerCompat#notify notify()}
+to send it to the wearable.</p>
+
+<pre style="clear:right">
+final static String GROUP_KEY_EMAILS = "group_key_emails";
+
+// Build the notification, setting the group appropriately
+Notification notif = new NotificationCompat.Builder(mContext)
+         .setContentTitle("New mail from " + sender1)
+         .setContentText(subject1)
+         .setSmallIcon(R.drawable.new_mail);
+         .setGroup(GROUP_KEY_EMAILS)
+         .build();
+
+// Issue the notification
+NotificationManagerCompat notificationManager =
+        NotificationManagerCompat.from(this);
+notificationManager.notify(notificationId1, notif);
+</pre>
+
+<p>Later on, when you create another notification, specify
+the same group key. When you call
+{@link android.support.v4.app.NotificationManagerCompat#notify notify()},
+this notification appears in the same stack as the previous notification,
+instead of as a new card:</p>
+
+<pre style="clear:right">
+Notification notif2 = new NotificationCompat.Builder(mContext)
+         .setContentTitle("New mail from " + sender2)
+         .setContentText(subject2)
+         .setSmallIcon(R.drawable.new_mail);
+         .setGroup(GROUP_KEY_EMAILS)
+         .build();
+
+notificationManager.notify(notificationId2, notif2);
+</pre>
+
+<p>By default, notifications appear in the order in which you added them, with the most recent
+  notification visible at the top.  You can order notifications in another fashion by calling
+  {@link android.support.v4.app.NotificationCompat.Builder#setSortKey setSortKey()}.</p>
+
+
+<h2 id="AddSummary">Add a Summary Notification</h2>
+
+<img src="{@docRoot}wear/images/notif_summary_framed.png" height="242" width="330" style="float:right;margin:0 0 20px 40px" alt="" />
+
+<p>It's important that you still provide a summary notification that appears on handheld devices.
+So in addition to adding each unique notification to the same stack group, also add a summary
+notification and call {@link android.support.v4.app.NotificationCompat.Builder#setGroupSummary setGroupSummary()}
+on the summary notification.</p>
+
+<p>This notification does not appear in your stack of notifications on the wearable, but
+appears as the only notification on the handheld device.</p>
+
+<pre style="clear:right">
+Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
+        R.drawable.ic_large_icon);
+
+// Create an InboxStyle notification
+Notification summaryNotification = new NotificationCompat.Builder(mContext)
+        .setContentTitle("2 new messages")
+        .setSmallIcon(R.drawable.ic_small_icon)
+        .setLargeIcon(largeIcon)
+        .setStyle(new NotificationCompat.InboxStyle()
+                .addLine("Alex Faaborg   Check this out")
+                .addLine("Jeff Chang   Launch Party")
+                .setBigContentTitle("2 new messages")
+                .setSummaryText("johndoe@gmail.com"))
+        .setGroup(GROUP_KEY_EMAILS)
+        .setGroupSummary(true)
+        .build();
+
+notificationManager.notify(notificationId3, summaryNotification);
+</pre>
+
+<p>
+This notification uses {@link android.support.v4.app.NotificationCompat.InboxStyle},
+which gives you an easy way to create notifications for email or messaging apps.
+You can use this style, another one defined in {@link android.support.v4.app.NotificationCompat},
+or no style for the summary notification.
+</p>
+
+<p class="note"><b>Tip:</b>
+To style the text like in the example screenshot, see
+<a href="{@docRoot}guide/topics/resources/string-resource.html#StylingWithHTML">Styling
+with HTML markup</a> and
+<a href="{@docRoot}guide/topics/resources/string-resource.html#StylingWithSpannables">Styling
+with Spannables</a>.
+</p>
+
+<p>Summary notifications can also affect notifications on wearables without being displayed on them.
+When creating a summary notification, you can use the
+{@link android.support.v4.app.NotificationCompat.WearableExtender} class and call
+{@link android.support.v4.app.NotificationCompat.WearableExtender#setBackground setBackground()} or
+{@link android.support.v4.app.NotificationCompat.WearableExtender#addAction addAction()} to set
+a background image or an action that applies to the entire stack on the wearable. For instance,
+to set the background for an entire stack of notifications:
+</p>
+
+<pre>
+Bitmap background = BitmapFactory.decodeResource(getResources(),
+        R.drawable.ic_background);
+
+NotificationCompat.WearableExtender wearableExtender =
+        new NotificationCompat.WearableExtender()
+        .setBackground(background);
+
+// Create an InboxStyle notification
+Notification summaryNotificationWithBackground =
+        new NotificationCompat.Builder(mContext)
+        .setContentTitle("2 new messages")
+        ...
+        .extend(wearableExtender)
+        .setGroup(GROUP_KEY_EMAILS)
+        .setGroupSummary(true)
+        .build();
+</pre>
\ No newline at end of file
diff --git a/docs/html/training/wearables/notifications/voice-input.jd b/docs/html/training/wearables/notifications/voice-input.jd
new file mode 100644
index 0000000..4a27826
--- /dev/null
+++ b/docs/html/training/wearables/notifications/voice-input.jd
@@ -0,0 +1,175 @@
+page.title=Receiving Voice Input in a Notification
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#VoiceInput">Define the Voice Input</a></li>
+  <li><a href="#AddAction">Add the Voice Input as a Notification Action</li>
+  <li><a href="#ReceiveInput">Receiving the Voice Input as a String</a>
+</ol>
+
+</div>
+</div>
+
+<p>If you have handheld notifications that include an action to input text,
+such as reply to an email, it should normally launch an activity
+on the handheld device to input the text. However, when your notification appears on a wearable,
+there is no keyboard input, so you can let users dictate a reply or provide pre-defined text messages
+using {@link android.support.v4.app.RemoteInput}.
+</p>
+
+<p>When users reply with voice or select one of the available
+messages, the system attaches the text response to the {@link android.content.Intent} you specified
+for the notification action and sends that intent to your handheld app.</p>
+
+<img src="{@docRoot}wear/images/13_voicereply.png" height="200" width="169"
+style="float:right;margin:0 0 20px 40px;clear:right" />
+<img src="{@docRoot}wear/images/03_actions.png" height="200" width="169"
+style="float:right;margin:0 0 20px 40px" />
+
+<p class="note"><strong>Note:</strong> The Android emulator does not support voice input. When
+using the emulator for a wearable device, enable <b>Hardware keyboard present</b> in the AVD settings
+so you can type replies instead.</p>
+
+<h2 id="VoiceInput">Define the Voice Input</h2>
+
+<p>To create an action that supports voice input, create an instance of 
+  {@link android.support.v4.app.RemoteInput.Builder} that you can add to your notification action.
+  This class's constructor accepts a string that the system uses as
+  the key for the voice input, which you'll later use to retrieve the text of the
+  input in your handheld app.</p>
+
+<p>For example, here's how to create a
+{@link android.support.v4.app.RemoteInput} object that provides a custom
+label for the voice input prompt:</p>
+
+<pre class="prettyprint">
+// Key for the string that's delivered in the action's intent
+private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
+
+String replyLabel = getResources().getString(R.string.reply_label);
+
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+        .setLabel(replyLabel)
+        .build();
+</pre>
+
+
+<h3>Add Pre-defined Text Responses</h3>
+
+<img src="{@docRoot}wear/images/12_voicereply.png" height="200"
+style="float:right;margin:0 0 20px 40px" />
+
+<p>In addition to allowing voice input, you can
+    provide up to five text responses that the user can select for quick replies. Call
+ {@link android.support.v4.app.RemoteInput.Builder#setChoices setChoices()} and pass it a string array.</p>
+
+<p>For example, you can define some responses in a resource array:</p>
+
+<p class="code-caption">res/values/strings.xml</code>
+<pre class="prettyprint">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+    &lt;string-array name="reply_choices">
+        &lt;item>Yes&lt;/item>
+        &lt;item>No&lt;/item>
+        &lt;item>Maybe&lt;/item>
+    &lt;/string-array>
+&lt;/resources>
+</pre>
+
+<p>Then, inflate the string array and add it to the
+ {@link android.support.v4.app.RemoteInput}:</p>
+
+<pre>
+public static final EXTRA_VOICE_REPLY = "extra_voice_reply";
+...
+String replyLabel = getResources().getString(R.string.reply_label);
+String[] replyChoices = getResources().getStringArray(R.array.reply_choices);
+
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+        .setLabel(replyLabel)
+        .setChoices(replyChoices)
+        .build();
+</pre>
+
+<h2 id="AddAction">Add the Voice Input as a Notification Action</h2>
+
+<p>
+To set the voice input, attach your
+{@link android.support.v4.app.RemoteInput} object to an action using
+{@link android.support.v4.app.NotificationCompat.Action.Builder#addRemoteInput addRemoteInput()}.
+You can then apply the action to the notification. For example:
+</p>
+
+<pre>
+// Create an intent for the reply action
+Intent replyIntent = new Intent(this, ReplyActivity.class);
+PendingIntent replyPendingIntent =
+        PendingIntent.getActivity(this, 0, replyIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+// Create the reply action and add the remote input
+NotificationCompat.Action action =
+        new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
+                getString(R.string.label, replyPendingIntent))
+                .addRemoteInput(remoteInput)
+                .build();
+
+// Build the notification and add the action via WearableExtender
+Notification notification =
+        new NotificationCompat.Builder(mContext)
+                .setSmallIcon(R.drawable.ic_message)
+                .setContentTitle(getString(R.string.title))
+                .setContentText(getString(R.string.content))
+                .extend(new WearableExtender().addAction(action))
+                .build();
+
+// Issue the notification
+NotificationManagerCompat notificationManager =
+        NotificationManagerCompat.from(mContext);
+notificationManager.notify(notificationId, notification);
+</pre>
+<p>
+When you issue this notification, users can swipe to the left to see the "Reply" action button.
+</p>
+
+<h2 id="ReceiveInput">Receiving the Voice Input as a String</h2>
+<p>
+To receive the user's transcribed message in the activity you declared in the reply action's intent,
+call {@link android.support.v4.app.RemoteInput#getResultsFromIntent getResultsFromIntent()},
+passing in the "Reply" action's intent. This method returns a {@link android.os.Bundle} that
+contains the text response. You can then query the {@link android.os.Bundle} to obtain the response.
+
+<p class="note"><b>Note:</b> Do not use {@link android.content.Intent#getExtras Intent.getExtras()}
+to obtain the voice result, because the voice input is stored as
+{@link android.content.ClipData}. The {@link android.support.v4.app.RemoteInput#getResultsFromIntent
+getResultsFromIntent()} method provides a convenient way to receive a character sequence without
+having to process the {@link android.content.ClipData} yourself.
+</p>
+
+<p>
+The following code shows a method that accepts an intent and returns the voice response,
+which is referenced by the <code>EXTRA_VOICE_REPLY</code> key that is used in the previous examples:
+</p>
+
+<pre>
+/**
+ * Obtain the intent that started this activity by calling
+ * Activity.getIntent() and pass it into this method to
+ * get the associated voice input string.
+ */
+
+private CharSequence getMessageText(Intent intent) {
+    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
+        if (remoteInput != null) {
+            return remoteInput.getCharSequence(EXTRA_VOICE_REPLY);
+        }
+    }
+    return null;
+}
+</pre>
\ No newline at end of file
diff --git a/docs/html/tv/images/atv-framed.png b/docs/html/tv/images/atv-framed.png
new file mode 100644
index 0000000..4cedab2
--- /dev/null
+++ b/docs/html/tv/images/atv-framed.png
Binary files differ
diff --git a/docs/html/tv/images/components.png b/docs/html/tv/images/components.png
new file mode 100644
index 0000000..5984c64
--- /dev/null
+++ b/docs/html/tv/images/components.png
Binary files differ
diff --git a/docs/html/tv/images/hero.jpg b/docs/html/tv/images/hero.jpg
index e951167..e9f8c47 100644
--- a/docs/html/tv/images/hero.jpg
+++ b/docs/html/tv/images/hero.jpg
Binary files differ
diff --git a/docs/html/tv/images/recommendations.png b/docs/html/tv/images/recommendations.png
new file mode 100644
index 0000000..e7aa01d
--- /dev/null
+++ b/docs/html/tv/images/recommendations.png
Binary files differ
diff --git a/docs/html/tv/images/search.png b/docs/html/tv/images/search.png
new file mode 100644
index 0000000..92e1e5f
--- /dev/null
+++ b/docs/html/tv/images/search.png
Binary files differ
diff --git a/docs/html/tv/index.jd b/docs/html/tv/index.jd
index 5c48e49..ff70977 100644
--- a/docs/html/tv/index.jd
+++ b/docs/html/tv/index.jd
@@ -27,11 +27,11 @@
             <div class="col-10">
               <div class="landing-section-header">
                 <div class="landing-h1 hero">Android TV</div>
-                <div class="landing-subhead hero">Your apps on the big screen</div>
+                <div class="landing-subhead hero">Big screen apps, games, and content</div>
                 <div class="landing-hero-description">
-                  <p>Engage users from the comfort of their couches.
-                    Put your app on TV and bring everyone into
-                    the action.</p>
+                  <p>Recommend great content to users right on the home screen.
+                    Enable users to find movies through voice search.
+                    Engage users with fluid, immersive games.</p>
                 </div>
               </div>
 
@@ -56,6 +56,7 @@
 
       <div class="landing-section" style="background-color:#f5f5f5" id="reimagine-your-app">
         <div class="wrap">
+
           <div class="landing-section-header">
             <div class="landing-h1">Reimagine Your App</div>
             <div class="landing-subhead">
@@ -63,50 +64,19 @@
             </div>
           </div>
 
-          <div class="landing-body">
-            <div class="landing-breakout cols">
-
-              <div class="col-3-wide">
-                <img src="{@docRoot}tv/images/placeholder-square.png" alt="">
-
-                <p>Simple</p>
-                <p class="landing-small">
-                  Smooth, fast interactions are key to a successful TV app. Keep navigation simple
-                  and light. Bring your content forward to let users enjoy it with a minimum of
-                  fuss.
-                </p>
-                <p class="landing-small">
-                  <a href="{@docRoot}design/tv/index.html">Learn about TV design</a>
-                </p>
-              </div>
-
-              <div class="col-3-wide">
-                <img src="{@docRoot}tv/images/placeholder-square.png" alt="">
-
-                <p>Cinematic</p>
-                <p class="landing-small">
-                  What would your app look like if it were a film? Use movement, animation and sound to make your app into an experience.
-                </p>
-                <p class="landing-small">
-                  <a href="{@docRoot}design/tv/index.html">Learn about TV design</a>
-                </p>
-              </div>
-
-              <div class="col-3-wide">
-                <img src="{@docRoot}tv/images/placeholder-square.png" alt="">
-
-                <p>Beautiful</p>
-                <p class="landing-small">
-                  Apps on TV should be a pleasure to look at, as well as enjoyable to use. Use
-                  made-for-TV styles to make your app familiar and fun.
-                </p>
-                <p class="landing-small">
-                  <a href="{@docRoot}design/tv/index.html">Learn about design for TV</a>
-                </p>
-              </div>
-            </div>
-
+          <div class="landing-body landing-align-center">
+            <img src="{@docRoot}tv/images/atv-framed.png" alt="Android TV" >
+            <p>Simple. Cinematic. Beautiful.</p>
+            <p class="landing-small">
+              Smooth, fast interactions are key to a successful TV app. Keep navigation simple
+              and light. <br>Bring your content forward to let users enjoy it with a minimum of
+              effort.
+            </p>
+            <p class="landing-small">
+              <a href="{@docRoot}preview/tv/design/index.html">Learn about design for TV</a>
+            </p>
           </div>
+
         </div>  <!-- end .wrap -->
       </div>  <!-- end .landing-section -->
 
@@ -125,7 +95,8 @@
             <div class="landing-breakout cols">
 
               <div class="col-3-wide">
-                <img src="{@docRoot}tv/images/placeholder-square.png" alt="">
+                <img src="{@docRoot}tv/images/components.png" alt="TV layout components"
+                  style="margin-left: 23px;">
 
                 <p>Made for TV</p>
                 <p class="landing-small">
@@ -138,7 +109,8 @@
               </div>
 
               <div class="col-3-wide">
-                <img src="{@docRoot}tv/images/placeholder-square.png" alt="">
+                <img src="{@docRoot}tv/images/search.png" alt="Search"
+                  style="margin-left: 23px;">
 
                 <p>Get Found</p>
                 <p class="landing-small">
@@ -150,7 +122,8 @@
               </div>
 
               <div class="col-3-wide">
-                <img src="{@docRoot}tv/images/placeholder-square.png" alt="">
+                <img src="{@docRoot}tv/images/recommendations.png" alt="Recommendations"
+                  style="margin-left: 23px;">
 
                 <p>Recommend</p>
                 <p class="landing-small">
@@ -168,7 +141,7 @@
         </div>  <!-- end .wrap -->
       </div> <!-- end .landing-section -->
 
-      <div class="landing-section landing-red-background">
+      <div class="landing-section landing-red-background" id="start">
         <div class="wrap">
           <div class="landing-section-header">
             <div class="landing-h1 landing-align-left">Get Started with Android TV</div>
@@ -180,10 +153,10 @@
           <div class="landing-body">
             <div class="landing-breakout cols">
               <div class="col-8" style="margin-left: -8px;">
-                <p style="font-size: 24px;">L-Preview SDK</p>
+                <p style="font-size: 24px;">L Developer Preview</p>
                 <p>
-                  The preview SDK includes all the tools you need to build and test apps for TV.
-                  Download it and start creating your big-screen app.
+                   Get all the tools you need to build and test TV apps. Download the preview and
+                   start creating your big-screen experience.
                 </p>
 
               </div>
@@ -191,8 +164,9 @@
               <div class="col-8">
                 <p style="font-size: 24px;">ADT-1 Developer Kit</p>
                 <p>
-                  Request an ADT-1 Developer Kit, a compact and powerful streaming media player
-                  and gamepad, ideal for developing and testing apps for TV.
+                  Request an <a href="{@docRoot}preview/tv/adt-1/index.html"
+                  style="color: white;"><u>ADT-1 Developer Kit</u></a>, a compact and powerful
+                  streaming media player and gamepad, ideal for developing and testing apps for TV.
                 </p>
 
               </div>
@@ -204,14 +178,15 @@
             <div class="landing-breakout cols">
 
               <div class="col-8">
-                <a href="{@docRoot}preview/setup-sdk.html" class="landing-button landing-primary">
-                  Download the Preview SDK
+                <a href="{@docRoot}preview/tv/start/index.html" class="landing-button landing-primary">
+                  Get Started
                 </a>
               </div>
 
               <div class="col-8">
-                <a href="{@docRoot}preview/tv/adt-1/request.html" class="landing-button landing-primary">
-                  Request ADT-1 Developer Kit
+                <a href="https://support.google.com/googleplay/android-developer/contact/adt_request"
+                  class="landing-button landing-primary">
+                  Request the ADT-1 Developer Kit
                 </a>
               </div>
             </div>
diff --git a/docs/html/wear/images/features/apps.png b/docs/html/wear/images/features/apps.png
new file mode 100644
index 0000000..dbbb5e5
--- /dev/null
+++ b/docs/html/wear/images/features/apps.png
Binary files differ
diff --git a/docs/html/wear/images/features/notifications.png b/docs/html/wear/images/features/notifications.png
new file mode 100644
index 0000000..128853c
--- /dev/null
+++ b/docs/html/wear/images/features/notifications.png
Binary files differ
diff --git a/docs/html/wear/images/features/s1.png b/docs/html/wear/images/features/s1.png
deleted file mode 100644
index ba96cf8..0000000
--- a/docs/html/wear/images/features/s1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/wear/images/features/s2.png b/docs/html/wear/images/features/s2.png
deleted file mode 100644
index af28496..0000000
--- a/docs/html/wear/images/features/s2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/wear/images/features/s3.png b/docs/html/wear/images/features/s3.png
deleted file mode 100644
index 6ae9868..0000000
--- a/docs/html/wear/images/features/s3.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/wear/images/features/s4.png b/docs/html/wear/images/features/s4.png
deleted file mode 100644
index 125713d..0000000
--- a/docs/html/wear/images/features/s4.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/wear/images/features/send-data.png b/docs/html/wear/images/features/send-data.png
new file mode 100644
index 0000000..7010e3f
--- /dev/null
+++ b/docs/html/wear/images/features/send-data.png
Binary files differ
diff --git a/docs/html/wear/images/features/ts1.png b/docs/html/wear/images/features/ts1.png
deleted file mode 100644
index 5d4b1c1..0000000
--- a/docs/html/wear/images/features/ts1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/wear/images/features/ts2.png b/docs/html/wear/images/features/ts2.png
deleted file mode 100644
index dc798c5..0000000
--- a/docs/html/wear/images/features/ts2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/wear/images/features/ts3.png b/docs/html/wear/images/features/ts3.png
deleted file mode 100644
index 0d68ebc..0000000
--- a/docs/html/wear/images/features/ts3.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/wear/images/features/ts4.png b/docs/html/wear/images/features/voice.png
similarity index 100%
rename from docs/html/wear/images/features/ts4.png
rename to docs/html/wear/images/features/voice.png
Binary files differ
diff --git a/docs/html/wear/images/notifications.png b/docs/html/wear/images/notifications.png
new file mode 100644
index 0000000..8b1cb0b
--- /dev/null
+++ b/docs/html/wear/images/notifications.png
Binary files differ
diff --git a/docs/html/wear/images/steps.png b/docs/html/wear/images/steps.png
new file mode 100644
index 0000000..965f382
--- /dev/null
+++ b/docs/html/wear/images/steps.png
Binary files differ
diff --git a/docs/html/wear/images/voicecommands.png b/docs/html/wear/images/voicecommands.png
new file mode 100644
index 0000000..9839ed8
--- /dev/null
+++ b/docs/html/wear/images/voicecommands.png
Binary files differ
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index bc08aa0..c9b8ba85 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -83,33 +83,35 @@
           <div class="landing-body">
             <div class="landing-breakout cols">
               <div class="col-3-wide">
-
-                <div class="framed-wear-square">
-                  <img src="{@docRoot}wear/images/screens/reservation_animated.gif">
+              <div class="framed-wear-square">
+                <img src="{@docRoot}wear/images/notifications.png" itemprop="image" alt="">
                 </div>
-
-                <p class="landing-small">
-                  Say “Ok Google” to ask questions and get stuff done.
-                </p>
-              </div>
-              <div class="col-3-wide">
-                <img src="{@docRoot}wear/images/screens/circle_message2.png" itemprop="image" alt="">
+                <br />
                 <p class="landing-small">
                   Get glanceable, actionable information at just the right time with notifications
                   that are synced from your handheld device.
-
                 </p>
               </div>
               <div class="col-3-wide">
-                <img src="{@docRoot}wear/images/screens/fitness-24.png" alt="">
+                <div class="framed-wear-square">
+                  <img src="{@docRoot}wear/images/voicecommands.png">
+                </div>
+                <br />
+                <p class="landing-small">
+                  Say “Ok Google” to send messages, ask questions, and get stuff done.
+                </p>
+              </div>
+              <div class="col-3-wide">
+              <div class="framed-wear-square">
+                <img src="{@docRoot}wear/images/steps.png" alt="">
+                </div>
+                <br />
                 <p class="landing-small">
                   Design apps that can access a wide range of sensors and other hardware
                    directly on the wearable.
-
                 </p>
               </div>
             </div>
-
             <p>
               Before you start building, check out the
               <a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a>
@@ -124,15 +126,15 @@
           <div class="landing-section-header">
             <div class="landing-h1">Developing for Android Wear</div>
             <div class="landing-subhead">
-             The Android Wear APIs are delivered in the Android v4 support library and Google Play services.
-             This lets Android handhelds, old and new, communicate with Android wearables.
-            </div>
+             The Android Wear APIs are delivered in the Android Support Library and Google Play
+             services. When using these libraries, handheld devices running Android 4.3
+             or later can communicate with wearables.</div>
           </div>
 
           <div class="landing-body">
             <div class="landing-breakout cols">
               <div class="col-4">
-                <img src="{@docRoot}wear/images/features/ts2.png" alt="">
+                <img src="{@docRoot}wear/images/features/notifications.png" alt="">
                 <p>Synced Notifications</p>
                 <p class="landing-small">
                   Notifications on handhelds can automatically sync to wearables, so design them
@@ -143,19 +145,29 @@
                 </p>
               </div>
               <div class="col-4">
-                <img src="{@docRoot}wear/images/features/ts1.png" alt="">
-                <p>Wearable Apps</p>
+                <img src="{@docRoot}wear/images/features/voice.png" alt="">
+                <p>Voice Actions</p>
+                <p class="landing-small">
+                  Register your app to handle voice actions, like "Ok Google, take a&nbsp;note,"
+                  for a hands-free experience.
+                </p>
+                <p class="landing-small">
+                  <a href="{@docRoot}training/wearables/apps/voice-actions.html">Integrate voice actions</a>
+                </p>
+              </div>
+              <div class="col-4">
+                <img src="{@docRoot}wear/images/features/apps.png" alt="">
+                <p>Build Wearable Apps</p>
                 <p class="landing-small">
                   Create custom experiences with activities, services, sensors, and much
                   more with the Android SDK.
                 </p>
                 <p class="landing-small">
                   <a href="{@docRoot}training/wearables/apps/index.html">Create wearable apps</a>
-
                 </p>
               </div>
               <div class="col-4">
-                <img src="{@docRoot}wear/images/features/ts2.png" alt="">
+                <img src="{@docRoot}wear/images/features/send-data.png" alt="">
                 <p>Send Data</p>
                 <p class="landing-small">
                   Send data and actions between handhelds and wearables with
@@ -166,17 +178,6 @@
 
                 </p>
               </div>
-              <div class="col-4">
-                <img src="{@docRoot}wear/images/features/ts4.png" alt="">
-                <p>Voice Actions</p>
-                <p class="landing-small">
-                  Register your app to handle voice actions, like "Ok Google, take a&nbsp;note,"
-                  for a hands-free experience.
-                </p>
-                <p class="landing-small">
-                  <a href="{@docRoot}training/wearables/apps/voice-actions.html">Integrate voice actions</a>
-                </p>
-              </div>
             </div>
           </div>
         </div> <!-- end .wrap -->
@@ -185,7 +186,7 @@
       <div class="landing-section landing-white-background">
         <div class="wrap">
           <div class="landing-section-header">
-            <div class="landing-h2">Building an Ecosystem</div>
+            <div class="landing-h1">Building an Ecosystem</div>
             <div class="landing-body landing-align-center">
               <p class="landing-small">
                 We’re working with partners around the world to build watches powered by Android Wear!
diff --git a/docs/html/wear/notifications/creating.jd b/docs/html/wear/notifications/creating.jd
deleted file mode 100644
index a5d7da7..0000000
--- a/docs/html/wear/notifications/creating.jd
+++ /dev/null
@@ -1,305 +0,0 @@
-page.title=Creating Notifications for Android Wear
-
-@jd:body
-
-
-<p>When an Android device such as a phone or tablet is connected to an Android wearable,
-all notifications are shared between the devices by default. On the Android wearable, each
-notification appears as a new card in the <a href="{@docRoot}wear/design/user-interface.html#Stream"
->context stream</a>.</p>
-
-<img src="{@docRoot}wear/images/notification_phone@2x.png" width="700" height="265" />
-
-
-<p>So without any effort, your app notifications are available to users on Android Wear.
-However, you can enhance the user experience in several ways. For instance,
-if users may respond to a notification by entering text, such as to reply to
-a message, you can add the ability for users to reply by voice directly from the
-wearable.</p>
-
-<p>To help you provide the best user experience
-for your notifications on Android Wear, this guide shows you how to
-build notifications using standard templates in
-the {@link android.support.v4.app.NotificationCompat.Builder} APIs, plus how to begin
-extending your notification's capabilities for the wearable user experience.</p>
-
-<p class="note"><strong>Note:</strong>
-Notifications using {@link android.widget.RemoteViews} are stripped of custom
-layouts and the system uses only the text and icons in the
-{@link android.app.Notification} object to
-display the notification in a card. However, custom card layouts will be supported by
-the official Android Wear SDK that is coming later.</p>
-</div>
-
-
-
-
-<h2 id="Import">Import the Necessary Classes</h2>
-
-<p>To begin development, you must first complete the instructions in the <a
-href="{@docRoot}wear/preview/start.html">Get Started with the Developer Preview</a> document.
-As mentioned in that document, your app must include
-both the <a href="http://developer.android.com/tools/support-library/features.html#v4">v4 support
-library</a> and the Developer Preview support library. So to get started,
-you should include the following imports in your project code:</p>
-
-<pre>
-import android.support.wearable.notifications.*;
-import android.support.wearable.app.NotificationManagerCompat;
-import android.support.v4.app.NotificationCompat;
-</pre>
-
-<p class="caution"><strong>Caution:</strong>
-The APIs in the current Android Wear Developer Preview are intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
-
-
-
-<h2 id="NotificationBuilder">Create Notifications with the Notification Builder</h2>
-
-<p>The <a href="http://developer.android.com/tools/support-library/features.html#v4">v4
-support library</a> allows you to create notifications using the latest notification features
-such as action buttons and large icons, while remaining compatible with Android 1.6 (API level
-4) and higher.</p>
-
-
-<p>For example, here's some code that creates and issues a notification using the
-{@link android.support.v4.app.NotificationCompat} APIs combined with the new
-<a href="{@docRoot}reference/android/support/wearable/app/NotificationManagerCompat.html">
-<code>NotificationManagerCompat</code></a> API:</p>
-
-
-<pre>
-int notificationId = 001;
-// Build intent for notification content
-Intent viewIntent = new Intent(this, ViewEventActivity.class);
-viewIntent.putExtra(EXTRA_EVENT_ID, eventId);
-PendingIntent viewPendingIntent =
-        PendingIntent.getActivity(this, 0, viewIntent, 0);
-
-NotificationCompat.Builder notificationBuilder =
-        new NotificationCompat.Builder(this)
-        .setSmallIcon(R.drawable.ic_event)
-        .setContentTitle(eventTitle)
-        .setContentText(eventLocation)
-        .setContentIntent(viewPendingIntent);
-
-// Get an instance of the NotificationManager service
-NotificationManagerCompat notificationManager =
-        NotificationManagerCompat.from(this);
-
-// Build the notification and issues it with notification manager.
-notificationManager.notify(notificationId, notificationBuilder.build());
-</pre>
-
-<p>When this notification appears on a handheld device, the user can invoke the
-{@link android.app.PendingIntent}
-specified by the {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
-setContentIntent()} method by touching the notification. When this
-notification appears on an Android wearable, the user can swipe the notification to the left to
-reveal the <strong>Open</strong> action, which invokes the intent on the handheld device.</p>
-
-
-
-
-
-
-<img src="{@docRoot}wear/images/circle_email_action.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
-
-<h2 id="ActionButtons">Add Action Buttons</h2>
-
-<p>In addition to the primary content action defined by
-{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
-setContentIntent()}, you can add other actions by passing a {@link android.app.PendingIntent} to
-the {@link android.support.v4.app.NotificationCompat.Builder#addAction
-addAction()} method.</p>
-
-<p>For example, the following code shows the same type of notification from above, but adds an
-action to view the event location on a map.</p>
-
-<pre style="clear:right">
-// Build an intent for an action to view a map
-Intent mapIntent = new Intent(Intent.ACTION_VIEW);
-Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));
-mapIntent.setData(geoUri);
-PendingIntent mapPendingIntent =
-        PendingIntent.getActivity(this, 0, mapIntent, 0);
-
-NotificationCompat.Builder notificationBuilder =
-        new NotificationCompat.Builder(this)
-        .setSmallIcon(R.drawable.ic_event)
-        .setContentTitle(eventTitle)
-        .setContentText(eventLocation)
-        .setContentIntent(viewPendingIntent)
-        <b>.addAction(R.drawable.ic_map,
-                getString(R.string.map), mapPendingIntent);</b>
-</pre>
-
-<p>On a handheld device, the action appears as an
-additional button attached to the notification. On an Android wearable, the action appears as
-a large button when the user swipes the notification to the left. When the user taps the action,
-the associated {@link android.content.Intent} is invoked on the handheld device.</p>
-
-<p class="note"><strong>Tip:</strong> If your notifications includes a "Reply" action
-  (such as for a messaging app), you can enhance the behavior by enabling
-  voice input replies directly from the Android wearable. For more information, read
-  <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from a Notification</a>.
-</p>
-
-<p>For details about designing action buttons (including the icon specifications), see the
-<a href="{@docRoot}wear/design/index.html#NotifictionActions">Design Principles of Android
-Wear</a>.</p>
-
-
-<h2 id="BigView">Add a Big View</h2>
-
-<img src="{@docRoot}wear/images/06_images.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>You can insert extended text content
-to your notification by adding one of the "big view" styles to your notification. On a
-handheld device, users can see the big view content by expanding the notification,
-while on Android Wear, the big view content is visible by default.</p>
-
-<p>To add the extended content to your notification, call {@link
-android.support.v4.app.NotificationCompat.Builder#setStyle setStyle()} on the {@link
-android.support.v4.app.NotificationCompat.Builder} object, passing it an instance of either
-{@link android.support.v4.app.NotificationCompat.BigTextStyle BigTextStyle} or
-{@link android.support.v4.app.NotificationCompat.InboxStyle InboxStyle}.</p>
-
-<p>For example, the following code adds an instance of
-{@link android.support.v4.app.NotificationCompat.BigTextStyle} to the event notification,
-in order to include the complete event description (which includes more text than can fit
-into the space provided for {@link android.support.v4.app.NotificationCompat.Builder#setContentText
-setContentText()}).</p>
-
-
-<pre style="clear:right">
-// Specify the 'big view' content to display the long
-// event description that may not fit the normal content text.
-BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
-bigStyle.bigText(eventDescription);
-
-NotificationCompat.Builder notificationBuilder =
-        new NotificationCompat.Builder(this)
-        .setSmallIcon(R.drawable.ic_event)
-        .setLargeIcon(BitmapFractory.decodeResource(
-                getResources(), R.drawable.notif_background))
-        .setContentTitle(eventTitle)
-        .setContentText(eventLocation)
-        .setContentIntent(viewPendingIntent)
-        .addAction(R.drawable.ic_map,
-                getString(R.string.map), mapPendingIntent)
-        <b>.setStyle(bigStyle);</b>
-</pre>
-
-<p>Notice that you can add a large background image to any notification using the
-{@link android.support.v4.app.NotificationCompat.Builder#setLargeIcon setLargeIcon()}
-method. For more information about designing notifications with large images, see the
-<a href="{@docRoot}wear/design/index.html#Images">Design Principles of Android
-Wear</a>.</p>
-
-
-
-<h2 id="NewFeatures">Add New Features for Wearables</h2>
-
-<p>The Android Wear preview support library provides new APIs that
-  allow you to enhance the user experience for notifications on a wearable device. For example,
-  you can add additional pages of content that users can view by swiping to the left, or add the ability
-for users to deliver your app a text response using voice input.</p>
-
-<p>To use these new APIs:</p>
-
-<ol>
-  <li>Create an instance of
-{@link android.support.v4.app.NotificationCompat.Builder}, setting the
-desired properties for your notification.</li>
-  <li>Create a
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#WearableNotificationOptions.Builder(android.content.Context)"> <code>WearableNotificationOptions.Builder</code></a>, setting the wearable-specific options for the notication.</li>
-  <li>Call <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#WearableNotificationOptions.Builder#applyTo"><code>WearableNotificationOptions.Builder.applyTo()</code>
-  </a>, passing in the {@link android.support.v4.app.NotificationCompat.Builder}. This applies
-  the wearable options to the notification.</li>
-</ol>
-
-<p>
-For example, the following code calls the
- <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#setHintHideIcon(boolean)">
-  <code>setHintHideIcon()</code></a> method to remove the app icon from the notification card.
-</p>
-
-<pre>
-// Create a NotificationCompat.Builder for standard notification features
- NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
-         .setContentTitle("New mail from " + sender)
-         .setContentText(subject)
-         .setSmallIcon(R.drawable.new_mail);
-// Create a WearablesNotificationOptions.Builder to add functionality for wearables
- Notification notif = new WearableNotificationOptions.Builder()
-         <b>.setHintHideIcon(true)</b>
-         .build()
-         .applyTo(builder); //apply wearable options to to the original notification
-         .build()
-</pre>
-
-<p>The
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#setHintHideIcon(boolean)">
-  <code>setHintHideIcon()</code></a> method is just one example of new notification features available with the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html"
-  ><code>WearableNotificationOptions.Builder</code></a> class.
-</p>
-
-
-<p>When you want to deliver your notifications, always use the
-  <a href="{@docRoot}reference/android/support/wearable/app/NotificationManagerCompat.html">
-  <code>NotificationManagerCompat</code></a> API instead of
-  {@link android.app.NotificationManager}:</p>
-
-<pre>
-// Get an instance of the NotificationManager service
-NotificationManagerCompat notificationManager =
-        NotificationManagerCompat.from(this);
-
-// Issue the notification with notification manager.
-notificationManager.notify(notificationId, notif);
-</pre>
-
-
-<p>If you use the framework's {@link android.app.NotificationManager}, some
-features from <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html"><code>WearableNotificationOptions.Builder</code></a>
-do not work.</p>
-
-
-<p>To continue enhancing your notifications for wearables using
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html"
-  ><code>WearableNotificationOptions.Builder</code></a> and other APIs in the
-  preview support library, see the following developer guides:</p>
-
-  <dl>
-    <dt><a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input
-from a Notification</a></dt>
-      <dd>Add an action that receives voice input from the user and delivers the
-transcribed message to your app.</dd>
-    <dt><a href="{@docRoot}wear/notifications/pages.html">Adding Pages to a Notification</a></dt>
-      <dd>Add additional pages of information that are visible when the user
-swipes to the left.</dd>
-    <dt><a href="{@docRoot}wear/notifications/stacks.html">Stacking Notifications</a></dt>
-      <dd>Place all similar notifications from your app in a stack, allowing each to be
-viewed individually without adding multiple cards to the card stream.</dd>
-  </dl>
-
-
-<div class="next-docs">
-
-<div class="col-12">
-  <h2 class="norule">You might also want to read:</h2>
-  <dl>
-    <dt><a href="{@docRoot}training/notify-user/index.html">Notifying the User</a></dt>
-    <dd>Learn more about how to create notifications.</dd>
-    <dt><a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a></dt>
-    <dd>Learn everything you need to know about the {@link android.content.Intent}
-APIs, used by notificaton actions.</dd>
-  </dl>
-</div>
-</div>
-
-
-</body>
-</html>
diff --git a/docs/html/wear/notifications/pages.jd b/docs/html/wear/notifications/pages.jd
deleted file mode 100644
index 7d18b3f..0000000
--- a/docs/html/wear/notifications/pages.jd
+++ /dev/null
@@ -1,65 +0,0 @@
-page.title=Adding Pages to a Notification
-
-@jd:body
-
-
-<img src="{@docRoot}wear/images/09_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
-<img src="{@docRoot}wear/images/08_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>When you'd like to provide more information without requiring users
-to open your app on their handheld device, you can
-add one or more pages to the notification on Android Wear. The additional pages
-appear immediately to the right of the main notification card.
-For information about when to use and how to design
-multiple pages, see the
-<a href="{@docRoot}wear/design/index.html#NotificationPages">Design Principles of Android
-Wear</a>.</p>
-
-<p>To create a notification with multiple pages:</p>
-<ol>
-    <li>Create the main notification (the first page) the way you'd like the notification to appear on a phone
-    or tablet.</li>
-    <li>Add pages one at a time with the
-<a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#addPage(android.app.Notification)">
-<code>addPage()</code></a> method, or add multiple pages in a {@link java.util.Collection} with the
-<a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#addPages(java.util.Collection<android.app.Notification>)">
-<code>addPages()</code></a> method.</li>
-    <li>Apply the pages to the main notification with the
-    <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.html#applyTo(android.support.v4.app.NotificationCompat.Builder)"
-    ><code>applyTo()</code></a> method.</li>
-</ol>
-
-
-<p>For example, here's some code that adds a second page to a notification:</p>
-
-<pre>
-// Create builder for the main notification
-NotificationCompat.Builder notificationBuilder =
-        new NotificationCompat.Builder(this)
-        .setSmallIcon(R.drawable.new_message)
-        .setContentTitle("Page 1")
-        .setContentText("Short message")
-        .setContentIntent(viewPendingIntent);
-
-// Create a big text style for the second page
-BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
-secondPageStyle.setBigContentTitle("Page 2")
-               .bigText("A lot of text...");
-
-// Create second page notification
-Notification secondPageNotification =
-        new NotificationCompat.Builder(this)
-        .setStyle(secondPageStyle)
-        .build();
-
-// Add second page with wearable options and apply to main notification
-Notification twoPageNotification =
-        new WearableNotificationsOptions.Builder()
-        .addPage(secondPageNotification)
-        .build()
-        .applyTo(notificationBuilder)
-        .build();
-</pre>
-
-</body>
-</html>
diff --git a/docs/html/wear/notifications/remote-input.jd b/docs/html/wear/notifications/remote-input.jd
deleted file mode 100644
index 4db8274..0000000
--- a/docs/html/wear/notifications/remote-input.jd
+++ /dev/null
@@ -1,241 +0,0 @@
-page.title=Receiving Voice Input from a Notification
-
-@jd:body
-
-<img src="{@docRoot}wear/images/13_voicereply.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-
-<img src="{@docRoot}wear/images/03_actions.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-
-<p>If your notification includes an action to respond with text,
-    such as to reply to an email, it should normally launch an activity
-    on the handheld device. However, when your notification appears on an Android wearable, you can
-    allow users to dictate a reply with voice input. You can also provide pre-defined text
-    messages for the user to select.</p>
-
-<p>When the user replies with voice or selects one of the available
-messages, the system sends the message to your app on the connected handheld device.
-The message is attached as an extra in the {@link android.content.Intent} you specified
-to be used for the notification action.</p>
-
-<p class="note"><strong>Note:</strong> When developing with the Android emulator,
-you must type text replies into the voice input field, so be sure you have enabled
-<strong>Hardware keyboard present</strong> in the AVD settings.</p>
-
-
-<h2 id="RemoteInput">Define the Remote Input</h2>
-
-<p>To create an action that supports voice input, first create an instance of
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.html">
-<code>RemoteInput</code></a> using the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> APIs.
-    The
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor takes a string that the system
-    will use as a key for the {@link android.content.Intent} extra that carries the reply message
-    to your app on the handheld.</p>
-
-<p>For example, here's how to create a new
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.html">
-<code>RemoteInput</code></a> object that provides a custom
-    label for the voice input prompt:</p>
-
-<pre class="prettyprint">
-// Key for the string that's delivered in the action's intent
-private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
-
-String replyLabel = getResources().getString(R.string.reply_label);
-
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
-        .setLabel(replyLabel)
-        .build();
-</pre>
-
-
-<h3>Add Pre-defined Text Responses</h3>
-
-<img src="{@docRoot}wear/images/12_voicereply.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>In addition to allowing voice input, you can
-    provide up to five text responses that the user can select for quick replies. Call
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.Builder.html#setChoices(java.lang.String[])"><code>setChoices()</code></a> and pass it a string array.</p>
-
-<p>For example, you may define some responses in a resource array:</p>
-
-<p class="code-caption">res/values/strings.xml</code>
-<pre class="prettyprint">
-&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;resources>
-    &lt;string-array name="reply_choices">
-        &lt;item>Yes&lt;/item>
-        &lt;item>No&lt;/item>
-        &lt;item>Maybe&lt;/item>
-    &lt;/string-array>
-&lt;/resources>
-</pre>
-
-<p>Then, inflate the string array and add it to the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a>:</p>
-
-<pre>
-String replyLabel = getResources().getString(R.string.reply_label);
-String[] replyChoices = getResources().getStringArray(R.array.reply_choices);
-
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
-        .setLabel(replyLabel)
-        .setChoices(replyChoices)
-        .build();
-</pre>
-
-
-
-
-<h2 id="PrimaryAction">Receive Voice Input for the Primary Action</h2>
-
-<p>If "Reply" is your notification's primary action (defined by the {@link
-android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}
-method), then you should attach the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the main action using
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#addRemoteInputForContentIntent(android.support.wearable.notifications.RemoteInput)">
-<code>addRemoteInputForContentIntent()</code></a>. For example:</p>
-
-<pre>
-// Create intent for reply action
-Intent replyIntent = new Intent(this, ReplyActivity.class);
-PendingIntent replyPendingIntent =
-        PendingIntent.getActivity(this, 0, replyIntent, 0);
-
-// Build the notification
-NotificationCompat.Builder replyNotificationBuilder =
-        new NotificationCompat.Builder(this)
-        .setSmallIcon(R.drawable.ic_new_message)
-        .setContentTitle("Message from Travis")
-        .setContentText("I love key lime pie!")
-        .setContentIntent(replyPendingIntent);
-
-// Create the remote input
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
-        .setLabel(replyLabel)
-        .build();
-
-// Add remote input to wearable options and apply to notification
-Notification replyNotification =
-        new WearableNotificationOptions.Builder()
-        .addRemoteInputForContentIntent(remoteInput)
-        .build()
-        .applyTo(replyNotificationBuilder)
-        .build();
-</pre>
-
-<p>By using
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#addRemoteInputForContentIntent(android.support.wearable.notifications.RemoteInput)">
-<code>addRemoteInputForContentIntent()</code></a> to add the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> object to the notification's primary action,
-the button that normally appears as an "Open" action becomes the "Reply" action
-and starts the voice input UI when users select it on Android Wear.</p>
-
-
-
-<h2 id="NewAction">Receive Voice Input for a Secondary Action</h2>
-
-<p>If the "Reply" action is not your notification's primary action and you want to enable
-voice input for a secondary action, add the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to a new action button defined by an
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableAction.html">
-<code>Action</code></a> object.</p>
-
-<p>You should instantiate the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableAction.html">
-<code>WearableAction</code></a> with the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableAction.Builder.html"><code>WearableAction.Builder()</code></a>
-constructor, which takes an icon and text label for the action button, plus the
-{@link android.app.PendingIntent}
-the system should use to invoke your app when the user selects the action. For example:</p>
-
-<pre>
-// Create the pending intent to fire when the user selects the action
-Intent replyIntent = new Intent(this, ReplyActivity.class);
-PendingIntent pendingReplyIntent =
-        PendingIntent.getActivity(this, 0, replyIntent, 0);
-
-// Create the remote input
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
-        .setLabel(replyLabel)
-        .build();
-
-// Create the notification action
-WearableAction replyAction = new WearableAction.Builder(R.drawable.ic_message,
-        "Reply", pendingIntent)
-        .addRemoteInput(remoteInput)
-        .build();
-</pre>
-
-
-<p>After you add the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableAction.html">
-<code>Wearablection</code></a>, set the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableAction.html">
-<code>WearableAction</code></a> on the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html"><code>WearableNotifications.Builder</code></a> using
-  <a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationsOptions.Builder.html#addAction(Action)"><code>addAction()</code></a>.
-For example:</p>
-
-<pre>
-// Create basic notification builder
-NotificationCompat.Builder replyNotificationBuilder =
-        new NotificationCompat.Builder(this)
-                .setContentTitle("New message");
-
-// Create the notification action and add remote input
-WearableAction replyAction = new WearableAction.Builder(R.drawable.ic_message,
-        "Reply", pendingIntent)
-        .addRemoteInput(remoteInput)
-        .build();
-
-// Create wearable notification and add action
-Notification replyNotification =
-        new WearableNotificationOptions.Builder()
-                .addAction(replyAction)
-                .build()
-                .applyTo(replyNotificationBuilder)
-                .build();
-</pre>
-
-
-<p>Now, when the user selects "Reply" from an Android wearable, the system prompts the user
-    for voice input (and shows the list of pre-defined replies, if provided).
-    Once the user completes a response, the system invokes
-    the {@link android.content.Intent} attached to the action and adds the
-<code>EXTRA_VOICE_REPLY</code> extra (the string
-    you passed to the
-  <a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor)
-  with the user's message as the string value.</p>
-
-<h2 id="ObtainInput">Obtaining the Voice Input as a String</h2>
-<p>To obtain the user's voice input, call
-<a href="{@docRoot}reference/android/support/wearable/notifications/RemoteInput.html#getResultsFromIntent(Intent)"><code>getResultsFromIntent()</code></a>,
-passing in the "Reply" action's intent. This method returns
-a {@link android.os.Bundle} that represents the intent's extras. You can then query the
-{@link android.os.Bundle} to obtain the user's voice input string.
-</p>
-<p>
-The following code shows a method that accepts an intent and returns the voice input string,
-which is referenced by the <code>EXTRA_VOICE_REPLY</code> key that is used in the previous examples:
-</p>
-<pre>
-/**
- * Obtain the intent that started this activity by calling
- * Activity.getIntent() and pass it into this method to
- * get the associated voice input string.
- */
-private String getMessageText(Intent intent) {
-    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
-        if (remoteInput != null) {
-            return remoteInput.getString(Intent.EXTRA_VOICE_REPLY);
-        }
-    }
-    return null;
-}
-</pre>
-
-</body>
-</html>
diff --git a/docs/html/wear/notifications/stacks.jd b/docs/html/wear/notifications/stacks.jd
deleted file mode 100644
index 3c3dc09..0000000
--- a/docs/html/wear/notifications/stacks.jd
+++ /dev/null
@@ -1,138 +0,0 @@
-page.title=Stacking Notifications
-
-@jd:body
-
-<img src="{@docRoot}wear/images/11_bundles_B.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" alt="" />
-<img src="{@docRoot}wear/images/11_bundles_A.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" alt="" />
-
-<p>When creating notifications for a handheld device, you should always aggregate similar
-notifications into a single summary notification. For example, if your app creates notifications
-for received messages, you should not show more than one notification
-on a handheld device&mdash;when more than one is message is received, use a single notification
-to provide a summary such as "2 new messages."</p>
-
-<p>However, a summary notification is less useful on an Android wearable because users
-are not able to read details from each message on the wearable (they must open your app on the
-handheld to view more information). So for the wearable device, you should
-group all the notifications together in a stack. The stack of notifications appears as a single
-card, which users can expand to view the details from each notification separately. The new
-<a href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a> method makes this possible while allowing you to still provide
-only one summary notification on the handheld device.</p>
-
-<p>For details about designing notification stacks, see the
-<a href="{@docRoot}wear/design/index.html#NotificationStacks">Design Principles of Android
-Wear</a>.</p>
-
-
-<h2 id="AddGroup">Add Each Notification to a Group</h2>
-
-<p>To create a stack, call <a
-href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a> for each notification you want in the stack and specify a
-group key. Then call <a href="{@docRoot}reference/android/support/wearable/app/NotificationManagerCompat.html#notify(int, android.app.Notification)"><code>notify()</code></a> to send it to the wearable.</p>
-
-<pre style="clear:right">
-final static String GROUP_KEY_EMAILS = "group_key_emails";
-
-// Build the notification
-NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
-         .setContentTitle("New mail from " + sender1)
-         .setContentText(subject1)
-         .setSmallIcon(R.drawable.new_mail);
-
-// Set the group with WearableNotificationOptions.Builder and apply to the notification
-Notification notif1 = new WearableNotificationOptions.Builder()
-         .setGroup(GROUP_KEY_EMAILS)
-         .build()
-         .applyTo(builder)
-         .build();
-
-// Issue the notification
-NotificationManagerCompat notificationManager =
-        NotificationManagerCompat.from(this);
-notificationManager.notify(notificationId1, notif);
-</pre>
-
-<p>Later on, when you create another notification, specify
-the same group key. When you call
-<a href="{@docRoot}reference/android/support/v4/app/NotificationManagerCompat.html#notify(int, android.app.Notification)"><code>notify()</code></a>,
-this notification appears in the same stack as the previous notification,
-instead of as a new card:</p>
-
-<pre style="clear:right">
-builder = new NotificationCompat.Builder(mContext)
-         .setContentTitle("New mail from " + sender2)
-         .setContentText(subject2)
-         .setSmallIcon(R.drawable.new_mail);
-
-// Use the same group as the previous notification
-Notification notif2 = new WearableNotificationOptions.Builder()
-         .setGroup(GROUP_KEY_EMAILS)
-         .build()
-         .applyTo(builder)
-         .build();
-
-notificationManager.notify(notificationId2, notif);
-</pre>
-
-<p>By default, notifications appear in the order in which you added them, with the most recent
-  notification visible at the top.  You can define a specific position in the group
-  by passing an order position as the second parameter for <a
-href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationOptions.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a>.</p>
-
-
-<h2 id="AddSummary">Add a Summary Notification</h2>
-
-<img src="{@docRoot}wear/images/notif_summary_framed.png" height="242" width="330" style="float:right;margin:0 0 20px 40px" alt="" />
-
-<p>It's important that you still provide a summary notification that appears on handheld devices.
-So in addition to adding each unique notification to the same stack group, also add a summary
-notification, but set its order position to be <a
-href="{@docRoot}reference/android/support/wearable/notifications/WearableNotificationsOptions.html#GROUP_ORDER_SUMMARY"><code>GROUP_ORDER_SUMMARY</code></a>.</p>
-
-<p>This notification does not appear in your stack of notifications on the wearable, but
-appears as the only notification on the handheld device.</p>
-
-<pre style="clear:right">
-Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
-        R.drawable.ic_large_icon);
-
-// Create an InboxStyle notification
-builder = new NotificationCompat.Builder(this)
-        .setContentTitle("2 new messages")
-        .setSmallIcon(R.drawable.ic_small_icon)
-        .setLargeIcon(largeIcon)
-        .setStyle(new NotificationCompat.InboxStyle()
-                .addLine("Alex Faaborg   Check this out")
-                .addLine("Jeff Chang   Launch Party")
-                .setBigContentTitle("2 new messages")
-                .setSummaryText("johndoe@gmail.com"));
-
-// Specify the notification to be the group summary
-Notification summaryNotification = new WearableNotificationOptions.Builder()
-        .setGroupSummary(GROUP_KEY_EMAILS)
-        .build()
-        .applyTo(builder)
-        .build();
-
-notificationManager.notify(notificationId3, summaryNotification);
-</pre>
-
-<p>
-This notification uses {@link android.support.v4.app.NotificationCompat.InboxStyle},
-which gives you an easy way to create notifications for email or messaging apps.
-You can use this style, another one defined in {@link android.support.v4.app.NotificationCompat},
-or no style for the summary notification.
-</p>
-
-<p class="note"><b>Tip:</b>
-To style the text like in the example screenshot, see
-<a href="{@docRoot}guide/topics/resources/string-resource.html#StylingWithHTML">Styling
-with HTML markup</a> and
-<a href="{@docRoot}guide/topics/resources/string-resource.html#StylingWithSpannables">Styling
-with Spannables</a>.
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 38b8aaf..ed44cde 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -16,12 +16,14 @@
 
 package android.graphics.drawable;
 
+import android.annotation.NonNull;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.Insets;
+import android.graphics.Outline;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.PorterDuff.Mode;
@@ -123,6 +125,14 @@
     }
 
     @Override
+    public boolean getOutline(@NonNull Outline outline) {
+        if (mCurrDrawable != null) {
+            return mCurrDrawable.getOutline(outline);
+        }
+        return false;
+    }
+
+    @Override
     public void setAlpha(int alpha) {
         if (!mHasAlpha || mAlpha != alpha) {
             mHasAlpha = true;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 5cea7c9..2f22392 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -16,12 +16,14 @@
 
 package android.graphics.drawable;
 
+import android.annotation.NonNull;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
+import android.graphics.Outline;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.Rect;
@@ -563,6 +565,16 @@
         }
     }
 
+    /**
+     * Builds an Outline from the first child Drawable, if present.
+     */
+    @Override
+    public boolean getOutline(@NonNull Outline outline) {
+        if (mLayerState.mNum < 1) return false;
+        final Drawable firstChild = mLayerState.mChildren[0].mDrawable;
+        return firstChild.getOutline(outline);
+    }
+
     @Override
     public void setHotspot(float x, float y) {
         final ChildDrawable[] array = mLayerState.mChildren;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index fb19242..c8b51e0 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2811,38 +2811,6 @@
      * Only useful for volume controllers.
      * @hide
      */
-    public int getRemoteStreamVolume() {
-        // TODO STOPSHIP switch callers to use media sessions instead
-        Log.e(TAG, "Need to implement new Remote Volume!");
-        return 0;
-    }
-
-    /**
-     * Only useful for volume controllers.
-     * @hide
-     */
-    public int getRemoteStreamMaxVolume() {
-        // TODO STOPSHIP switch callers to use media sessions instead
-        Log.e(TAG, "Need to implement new Remote Volume!");
-        return 0;
-    }
-
-    /**
-     * Only useful for volume controllers.
-     * @hide
-     */
-    public void setRemoteStreamVolume(int index) {
-        try {
-            getService().setRemoteStreamVolume(index);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error setting remote stream volume", e);
-        }
-    }
-
-    /**
-     * Only useful for volume controllers.
-     * @hide
-     */
     public boolean isStreamAffectedByRingerMode(int streamType) {
         try {
             return getService().isStreamAffectedByRingerMode(streamType);
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 0c224a6..8dd2721 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -85,6 +85,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -849,10 +850,8 @@
         }
 
         if (streamType == STREAM_REMOTE_MUSIC) {
-            // don't play sounds for remote
-            flags &= ~(AudioManager.FLAG_PLAY_SOUND|AudioManager.FLAG_FIXED_VOLUME);
-            //if (DEBUG_VOL) Log.i(TAG, "Need to adjust remote volume: calling adjustRemoteVolume()");
-            mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, flags);
+            // TODO bounce it to MediaSessionService to find an appropriate
+            // session
         } else {
             adjustStreamVolume(streamType, direction, flags, callingPackage);
         }
@@ -4794,4 +4793,91 @@
         }
         mVolumeController.setController(controller);
     }
+
+    public static class VolumeController {
+        private static final String TAG = "VolumeController";
+
+        private IVolumeController mController;
+
+        public void setController(IVolumeController controller) {
+            mController = controller;
+        }
+
+        public boolean isSameBinder(IVolumeController controller) {
+            return Objects.equals(asBinder(), binder(controller));
+        }
+
+        public IBinder asBinder() {
+            return binder(mController);
+        }
+
+        private static IBinder binder(IVolumeController controller) {
+            return controller == null ? null : controller.asBinder();
+        }
+
+        @Override
+        public String toString() {
+            return "VolumeController(" + asBinder() + ")";
+        }
+
+        public void postDisplaySafeVolumeWarning(int flags) {
+            if (mController == null)
+                return;
+            try {
+                mController.displaySafeVolumeWarning(flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
+            }
+        }
+
+        public void postVolumeChanged(int streamType, int flags) {
+            if (mController == null)
+                return;
+            try {
+                mController.volumeChanged(streamType, flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling volumeChanged", e);
+            }
+        }
+
+        public void postMasterVolumeChanged(int flags) {
+            if (mController == null)
+                return;
+            try {
+                mController.masterVolumeChanged(flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling masterVolumeChanged", e);
+            }
+        }
+
+        public void postMasterMuteChanged(int flags) {
+            if (mController == null)
+                return;
+            try {
+                mController.masterMuteChanged(flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling masterMuteChanged", e);
+            }
+        }
+
+        public void setLayoutDirection(int layoutDirection) {
+            if (mController == null)
+                return;
+            try {
+                mController.setLayoutDirection(layoutDirection);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling setLayoutDirection", e);
+            }
+        }
+
+        public void postDismiss() {
+            if (mController == null)
+                return;
+            try {
+                mController.dismiss();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error calling dismiss", e);
+            }
+        }
+    }
 }
diff --git a/media/java/android/media/IRemoteVolumeController.aidl b/media/java/android/media/IRemoteVolumeController.aidl
new file mode 100644
index 0000000..e4a4a42
--- /dev/null
+++ b/media/java/android/media/IRemoteVolumeController.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.session.ISessionController;
+
+/**
+ * AIDL for the MediaSessionService to report interesting events on remote playback
+ * to a volume control dialog. See also IVolumeController for the AudioService half.
+ * TODO add in better support for multiple remote sessions.
+ * @hide
+ */
+oneway interface IRemoteVolumeController {
+    void remoteVolumeChanged(ISessionController session, int flags);
+    // sets the default session to use with the slider, replaces remoteSliderVisibility
+    // on IVolumeController
+    void updateRemoteController(ISessionController session);
+}
diff --git a/media/java/android/media/IVolumeController.aidl b/media/java/android/media/IVolumeController.aidl
index 35d7708..e3593a6 100644
--- a/media/java/android/media/IVolumeController.aidl
+++ b/media/java/android/media/IVolumeController.aidl
@@ -16,17 +16,12 @@
 
 package android.media;
 
-
 /**
- * AIDL for the AudioService to report interesting events to a remote volume control dialog.
+ * AIDL for the AudioService to report interesting events to a volume control
+ * dialog in another process.
  * @hide
  */
 oneway interface IVolumeController {
-    void hasNewRemotePlaybackInfo();
-
-    void remoteVolumeChanged(int streamType, int flags);
-
-    void remoteSliderVisibility(boolean visible);
 
     void displaySafeVolumeWarning(int flags);
 
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index a4a7c4e..6004ecf 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -77,7 +77,7 @@
     private final MediaEventHandler mEventHandler;
     private final Context mContext;
     private final ContentResolver mContentResolver;
-    private final VolumeController mVolumeController;
+    private final AudioService.VolumeController mVolumeController;
     private final BroadcastReceiver mReceiver = new PackageIntentsReceiver();
     private final AppOpsManager mAppOps;
     private final KeyguardManager mKeyguardManager;
@@ -85,7 +85,7 @@
     private final NotificationListenerObserver mNotifListenerObserver;
 
     protected MediaFocusControl(Looper looper, Context cntxt,
-            VolumeController volumeCtrl, AudioService as) {
+            AudioService.VolumeController volumeCtrl, AudioService as) {
         mEventHandler = new MediaEventHandler(looper);
         mContext = cntxt;
         mContentResolver = mContext.getContentResolver();
@@ -2061,29 +2061,6 @@
         }
     }
 
-    protected void adjustRemoteVolume(int streamType, int direction, int flags) {
-        int rccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
-        boolean volFixed = false;
-        synchronized (mMainRemote) {
-            if (!mMainRemoteIsActive) {
-                if (DEBUG_VOL) Log.w(TAG, "adjustRemoteVolume didn't find an active client");
-                return;
-            }
-            rccId = mMainRemote.mRccId;
-            volFixed = (mMainRemote.mVolumeHandling ==
-                    RemoteControlClient.PLAYBACK_VOLUME_FIXED);
-        }
-        // unlike "local" stream volumes, we can't compute the new volume based on the direction,
-        // we can only notify the remote that volume needs to be updated, and we'll get an async'
-        // update through setPlaybackInfoForRcc()
-        if (!volFixed) {
-            sendVolumeUpdateToRemote(rccId, direction);
-        }
-
-        // fire up the UI
-        mVolumeController.postRemoteVolumeChanged(streamType, flags);
-    }
-
     private void sendVolumeUpdateToRemote(int rccId, int direction) {
         if (DEBUG_VOL) { Log.d(TAG, "sendVolumeUpdateToRemote(rccId="+rccId+" , dir="+direction); }
         if (direction == 0) {
@@ -2183,27 +2160,9 @@
     }
 
     private void onReevaluateRemote() {
-        if (DEBUG_VOL) { Log.w(TAG, "onReevaluateRemote()"); }
-        // is there a registered RemoteControlClient that is handling remote playback
-        boolean hasRemotePlayback = false;
-        synchronized (mPRStack) {
-            // iteration stops when PLAYBACK_TYPE_REMOTE is found, so remote control stack
-            //   traversal order doesn't matter
-            Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
-            while(stackIterator.hasNext()) {
-                PlayerRecord prse = stackIterator.next();
-                if (prse.mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE) {
-                    hasRemotePlayback = true;
-                    break;
-                }
-            }
-        }
-        synchronized (mMainRemote) {
-            if (mHasRemotePlayback != hasRemotePlayback) {
-                mHasRemotePlayback = hasRemotePlayback;
-                mVolumeController.postRemoteSliderVisibility(hasRemotePlayback);
-            }
-        }
+        // TODO This was used to notify VolumePanel if there was remote playback
+        // in the stack. This is now in MediaSessionService. More code should be
+        // removed.
     }
 
 }
diff --git a/media/java/android/media/VolumeController.java b/media/java/android/media/VolumeController.java
deleted file mode 100644
index 6b70cc3..0000000
--- a/media/java/android/media/VolumeController.java
+++ /dev/null
@@ -1,135 +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.media;
-
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.Objects;
-
-/**
- * Wraps the remote volume controller interface as a convenience to audio service.
- * @hide
- */
-public class VolumeController {
-    private static final String TAG = "VolumeController";
-
-    private IVolumeController mController;
-
-    public void setController(IVolumeController controller) {
-        mController = controller;
-    }
-
-    public boolean isSameBinder(IVolumeController controller) {
-        return Objects.equals(asBinder(), binder(controller));
-    }
-
-    public IBinder asBinder() {
-        return binder(mController);
-    }
-
-    private static IBinder binder(IVolumeController controller) {
-        return controller == null ? null : controller.asBinder();
-    }
-
-    @Override
-    public String toString() {
-        return "VolumeController(" + asBinder() + ")";
-    }
-
-    public void postHasNewRemotePlaybackInfo() {
-        if (mController == null) return;
-        try {
-            mController.hasNewRemotePlaybackInfo();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling hasNewRemotePlaybackInfo", e);
-        }
-    }
-
-    public void postRemoteVolumeChanged(int streamType, int flags) {
-        if (mController == null) return;
-        try {
-            mController.remoteVolumeChanged(streamType, flags);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling remoteVolumeChanged", e);
-        }
-    }
-
-    public void postRemoteSliderVisibility(boolean visible) {
-        if (mController == null) return;
-        try {
-            mController.remoteSliderVisibility(visible);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling remoteSliderVisibility", e);
-        }
-    }
-
-    public void postDisplaySafeVolumeWarning(int flags) {
-        if (mController == null) return;
-        try {
-            mController.displaySafeVolumeWarning(flags);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
-        }
-    }
-
-    public void postVolumeChanged(int streamType, int flags) {
-        if (mController == null) return;
-        try {
-            mController.volumeChanged(streamType, flags);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling volumeChanged", e);
-        }
-    }
-
-    public void postMasterVolumeChanged(int flags) {
-        if (mController == null) return;
-        try {
-            mController.masterVolumeChanged(flags);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling masterVolumeChanged", e);
-        }
-    }
-
-    public void postMasterMuteChanged(int flags) {
-        if (mController == null) return;
-        try {
-            mController.masterMuteChanged(flags);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling masterMuteChanged", e);
-        }
-    }
-
-    public void setLayoutDirection(int layoutDirection) {
-        if (mController == null) return;
-        try {
-            mController.setLayoutDirection(layoutDirection);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling setLayoutDirection", e);
-        }
-    }
-
-    public void postDismiss() {
-        if (mController == null) return;
-        try {
-            mController.dismiss();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error calling dismiss", e);
-        }
-    }
-}
\ No newline at end of file
diff --git a/media/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl
index e823153..baa1379 100644
--- a/media/java/android/media/session/ISessionControllerCallback.aidl
+++ b/media/java/android/media/session/ISessionControllerCallback.aidl
@@ -17,6 +17,7 @@
 
 import android.media.MediaMetadata;
 import android.media.session.RouteInfo;
+import android.media.session.ParcelableVolumeInfo;
 import android.media.session.PlaybackState;
 import android.os.Bundle;
 
@@ -30,4 +31,5 @@
     // These callbacks are for the TransportController
     void onPlaybackStateChanged(in PlaybackState state);
     void onMetadataChanged(in MediaMetadata metadata);
+    void onVolumeInfoChanged(in ParcelableVolumeInfo info);
 }
\ No newline at end of file
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index bd1fa85..dce84d4 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -16,6 +16,7 @@
 package android.media.session;
 
 import android.content.ComponentName;
+import android.media.IRemoteVolumeController;
 import android.media.session.IActiveSessionsListener;
 import android.media.session.ISession;
 import android.media.session.ISessionCallback;
@@ -34,4 +35,7 @@
     void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName,
             int userId);
     void removeSessionsListener(in IActiveSessionsListener listener);
+
+    // This is for the system volume UI only
+    void setRemoteVolumeController(in IRemoteVolumeController rvc);
 }
\ No newline at end of file
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index cc3db26..7653e5a 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.media.AudioManager;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
@@ -52,6 +53,7 @@
     private static final int MSG_UPDATE_PLAYBACK_STATE = 2;
     private static final int MSG_UPDATE_METADATA = 3;
     private static final int MSG_ROUTE = 4;
+    private static final int MSG_UPDATE_VOLUME = 5;
 
     private final ISessionController mSessionBinder;
 
@@ -203,6 +205,43 @@
     }
 
     /**
+     * Set the volume of the stream or output this session is playing on. The
+     * command will be ignored if it does not support
+     * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
+     * {@link AudioManager} may be used to affect the handling.
+     *
+     * @see #getVolumeInfo()
+     * @param value The value to set it to, between 0 and the reported max.
+     * @param flags Any flags to pass with the command.
+     */
+    public void setVolumeTo(int value, int flags) {
+        try {
+            mSessionBinder.setVolumeTo(value, flags);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error calling setVolumeTo.", e);
+        }
+    }
+
+    /**
+     * Adjust the volume of the stream or output this session is playing on.
+     * Negative values will lower the volume. The command will be ignored if it
+     * does not support {@link VolumeProvider#VOLUME_CONTROL_RELATIVE} or
+     * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
+     * {@link AudioManager} may be used to affect the handling.
+     *
+     * @see #getVolumeInfo()
+     * @param delta The number of steps to adjust the volume by.
+     * @param flags Any flags to pass with the command.
+     */
+    public void adjustVolumeBy(int delta, int flags) {
+        try {
+            mSessionBinder.adjustVolumeBy(delta, flags);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
+        }
+    }
+
+    /**
      * Adds a callback to receive updates from the Session. Updates will be
      * posted on the caller's thread.
      *
@@ -406,6 +445,14 @@
          */
         public void onMetadataChanged(@Nullable MediaMetadata metadata) {
         }
+
+        /**
+         * Override to handle changes to the volume info.
+         *
+         * @param info The current volume info for this session.
+         */
+        public void onVolumeInfoChanged(VolumeInfo info) {
+        }
     }
 
     /**
@@ -552,8 +599,8 @@
         /**
          * Get the type of volume handling, either local or remote. One of:
          * <ul>
-         * <li>{@link MediaSession#VOLUME_TYPE_LOCAL}</li>
-         * <li>{@link MediaSession#VOLUME_TYPE_REMOTE}</li>
+         * <li>{@link MediaSession#PLAYBACK_TYPE_LOCAL}</li>
+         * <li>{@link MediaSession#PLAYBACK_TYPE_REMOTE}</li>
          * </ul>
          *
          * @return The type of volume handling this session is using.
@@ -564,7 +611,7 @@
 
         /**
          * Get the stream this is currently controlling volume on. When the volume
-         * type is {@link MediaSession#VOLUME_TYPE_REMOTE} this value does not
+         * type is {@link MediaSession#PLAYBACK_TYPE_REMOTE} this value does not
          * have meaning and should be ignored.
          *
          * @return The stream this session is playing on.
@@ -646,6 +693,16 @@
             }
         }
 
+        @Override
+        public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) {
+            MediaController controller = mController.get();
+            if (controller != null) {
+                VolumeInfo info = new VolumeInfo(pvi.volumeType, pvi.audioStream, pvi.controlType,
+                        pvi.maxVolume, pvi.currentVolume);
+                controller.postMessage(MSG_UPDATE_VOLUME, info, null);
+            }
+        }
+
     }
 
     private final static class MessageHandler extends Handler {
@@ -671,6 +728,9 @@
                 case MSG_UPDATE_METADATA:
                     mCallback.onMetadataChanged((MediaMetadata) msg.obj);
                     break;
+                case MSG_UPDATE_VOLUME:
+                    mCallback.onVolumeInfoChanged((VolumeInfo) msg.obj);
+                    break;
             }
         }
 
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 8909d55..7637ec8 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -127,12 +127,12 @@
     /**
      * The session uses local playback.
      */
-    public static final int VOLUME_TYPE_LOCAL = 1;
+    public static final int PLAYBACK_TYPE_LOCAL = 1;
 
     /**
      * The session uses remote playback.
      */
-    public static final int VOLUME_TYPE_REMOTE = 2;
+    public static final int PLAYBACK_TYPE_REMOTE = 2;
 
     private final Object mLock = new Object();
 
@@ -265,7 +265,7 @@
      */
     public void setPlaybackToLocal(int stream) {
         try {
-            mBinder.configureVolumeHandling(VOLUME_TYPE_LOCAL, stream, 0);
+            mBinder.configureVolumeHandling(PLAYBACK_TYPE_LOCAL, stream, 0);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setPlaybackToLocal.", e);
         }
@@ -294,7 +294,7 @@
         });
 
         try {
-            mBinder.configureVolumeHandling(VOLUME_TYPE_REMOTE, volumeProvider.getVolumeControl(),
+            mBinder.configureVolumeHandling(PLAYBACK_TYPE_REMOTE, volumeProvider.getVolumeControl(),
                     volumeProvider.getMaxVolume());
         } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setPlaybackToRemote.", e);
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 882453f..9291bb0 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
+import android.media.IRemoteVolumeController;
 import android.media.session.ISessionManager;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -215,6 +216,21 @@
     }
 
     /**
+     * Set the remote volume controller to receive volume updates on. Only for
+     * use by system UI.
+     *
+     * @param rvc The volume controller to receive updates on.
+     * @hide
+     */
+    public void setRemoteVolumeController(IRemoteVolumeController rvc) {
+        try {
+            mService.setRemoteVolumeController(rvc);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in setRemoteVolumeController.", e);
+        }
+    }
+
+    /**
      * Send a media key event. The receiver will be selected automatically.
      *
      * @param keyEvent The KeyEvent to send.
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 409a33c..0f4a930 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -560,8 +560,11 @@
          */
         int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
             if (DEBUG) Log.d(TAG, "dispatchInputEvent(" + event + ")");
+            boolean isNavigationKey = false;
             if (event instanceof KeyEvent) {
-                if (((KeyEvent) event).dispatch(this, mDispatcherState, this)) {
+                KeyEvent keyEvent = (KeyEvent) event;
+                isNavigationKey = isNavigationKey(keyEvent.getKeyCode());
+                if (keyEvent.dispatch(this, mDispatcherState, this)) {
                     return TvInputManager.Session.DISPATCH_HANDLED;
                 }
             } else if (event instanceof MotionEvent) {
@@ -587,8 +590,18 @@
             if (!mOverlayView.hasWindowFocus()) {
                 mOverlayView.getViewRootImpl().windowFocusChanged(true, true);
             }
-            mOverlayView.getViewRootImpl().dispatchInputEvent(event, receiver);
-            return TvInputManager.Session.DISPATCH_IN_PROGRESS;
+            if (isNavigationKey && mOverlayView.hasFocusable()) {
+                // If mOverlayView has focusable views, navigation key events should be always
+                // handled. If not, it can make the application UI navigation messed up.
+                // For example, in the case that the left-most view is focused, a left key event
+                // will not be handled in ViewRootImpl. Then, the left key event will be handled in
+                // the application during the UI navigation of the TV input.
+                mOverlayView.getViewRootImpl().dispatchInputEvent(event);
+                return TvInputManager.Session.DISPATCH_HANDLED;
+            } else {
+                mOverlayView.getViewRootImpl().dispatchInputEvent(event, receiver);
+                return TvInputManager.Session.DISPATCH_IN_PROGRESS;
+            }
         }
 
         private void setSessionCallback(ITvInputSessionCallback callback) {
@@ -596,6 +609,26 @@
         }
     }
 
+    /** @hide */
+    public static boolean isNavigationKey(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+            case KeyEvent.KEYCODE_PAGE_UP:
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+            case KeyEvent.KEYCODE_MOVE_HOME:
+            case KeyEvent.KEYCODE_MOVE_END:
+            case KeyEvent.KEYCODE_TAB:
+            case KeyEvent.KEYCODE_SPACE:
+            case KeyEvent.KEYCODE_ENTER:
+                return true;
+        }
+        return false;
+    }
+
     private final class ServiceHandler extends Handler {
         private static final int DO_CREATE_SESSION = 1;
         private static final int DO_BROADCAST_AVAILABILITY_CHANGE = 2;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e9cb197..0df6c74 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -300,5 +300,11 @@
                 <category android:name="android.intent.category.DESK_DOCK" />
             </intent-filter>
         </activity>
+
+
+        <!-- I dream of notifications -->
+        <service
+            android:name=".doze.DozeService"
+            android:exported="true" />
     </application>
 </manifest>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 36c1994..370ff1c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -97,34 +97,6 @@
     <!-- half the distance between notifications in the panel -->
     <dimen name="notification_divider_height">2dp</dimen>
 
-    <!-- Notification drawer tuning parameters (phone UI) -->
-    <!-- Initial velocity of the shade when expanding on its own -->
-    <dimen name="self_expand_velocity">2000dp</dimen>
-    <!-- Initial velocity of the shade when collapsing on its own -->
-    <dimen name="self_collapse_velocity">2000dp</dimen>
-    <!-- Minimum final velocity of gestures interpreted as expand requests -->
-    <dimen name="fling_expand_min_velocity">100dp</dimen>
-    <!-- Minimum final velocity of gestures interpreted as collapse requests -->
-    <dimen name="fling_collapse_min_velocity">100dp</dimen>
-    <!-- Cap on contribution of x dimension of gesture to overall velocity -->
-    <dimen name="fling_gesture_max_x_velocity">200dp</dimen>
-    <!-- Cap on overall resulting fling speed (s^-1) -->
-    <dimen name="fling_gesture_max_output_velocity">3000dp</dimen>
-
-    <!-- Minimum distance a fling must travel (anti-jitter) -->
-    <dimen name="fling_gesture_min_dist">20dp</dimen>
-
-    <!-- Minimum fraction of the display a gesture must travel, at any velocity, to qualify as a
-         collapse request -->
-    <item type="dimen" name="collapse_min_display_fraction">10%</item>
-    <!-- Minimum fraction of the display a gesture must travel to qualify as an expand request -->
-    <item type="dimen" name="expand_min_display_fraction">50%</item>
-
-    <!-- Initial acceleration of an expand animation after fling -->
-    <dimen name="expand_accel">2000dp</dimen>
-    <!-- Initial acceleration of an collapse animation after fling -->
-    <dimen name="collapse_accel">2000dp</dimen>
-
     <!-- The padding on the global screenshot background image -->
     <dimen name="global_screenshot_bg_padding">20dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
new file mode 100644
index 0000000..cc0d4a7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -0,0 +1,238 @@
+/*
+ * 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.doze;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.TriggerEvent;
+import android.hardware.TriggerEventListener;
+import android.os.PowerManager;
+import android.os.Vibrator;
+import android.service.dreams.DozeHardware;
+import android.service.dreams.DreamService;
+import android.util.Log;
+
+import com.android.systemui.SystemUIApplication;
+
+public class DozeService extends DreamService {
+    private static final boolean DEBUG = false;
+
+    private static final String TEASE_ACTION = "com.android.systemui.doze.tease";
+
+    private final String mTag = String.format("DozeService.%08x", hashCode());
+    private final Context mContext = this;
+
+    private Host mHost;
+    private DozeHardware mDozeHardware;
+    private SensorManager mSensors;
+    private Sensor mSigMotionSensor;
+    private PowerManager mPowerManager;
+    private PowerManager.WakeLock mWakeLock;
+    private boolean mDreaming;
+    private boolean mTeaseReceiverRegistered;
+
+    public DozeService() {
+        if (DEBUG) Log.d(mTag, "new DozeService()");
+        setDebug(DEBUG);
+    }
+
+    @Override
+    public void onCreate() {
+        if (DEBUG) Log.d(mTag, "onCreate");
+        super.onCreate();
+
+        if (getApplication() instanceof SystemUIApplication) {
+            final SystemUIApplication app = (SystemUIApplication) getApplication();
+            mHost = app.getComponent(Host.class);
+        }
+
+        setWindowless(true);
+
+        mSensors = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+        mSigMotionSensor = mSensors.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        if (DEBUG) Log.d(mTag, "onAttachedToWindow");
+        super.onAttachedToWindow();
+    }
+
+    @Override
+    public void onDreamingStarted() {
+        super.onDreamingStarted();
+        mDozeHardware = getDozeHardware();
+        if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze()
+                + " dozeHardware=" + mDozeHardware);
+        mDreaming = true;
+        listenForTeaseSignals(true);
+        requestDoze();
+    }
+
+    public void stayAwake(long millis) {
+        if (mDreaming && millis > 0) {
+            mWakeLock.acquire(millis);
+        }
+    }
+
+    public void startDozing() {
+        if (DEBUG) Log.d(mTag, "startDozing mDreaming=" + mDreaming);
+        if (!mDreaming) {
+            Log.w(mTag, "Not dozing, no longer dreaming");
+            return;
+        }
+
+        super.startDozing();
+    }
+
+    @Override
+    public void onDreamingStopped() {
+        if (DEBUG) Log.d(mTag, "onDreamingStopped isDozing=" + isDozing());
+        super.onDreamingStopped();
+
+        mDreaming = false;
+        mDozeHardware = null;
+        if (mWakeLock.isHeld()) {
+            mWakeLock.release();
+        }
+        listenForTeaseSignals(false);
+        stopDozing();
+        dozingStopped();
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
+        super.onDetachedFromWindow();
+
+        dozingStopped();
+    }
+
+    @Override
+    public void onDestroy() {
+        if (DEBUG) Log.d(mTag, "onDestroy");
+        super.onDestroy();
+
+        dozingStopped();
+    }
+
+    private void requestDoze() {
+        if (mHost != null) {
+            mHost.requestDoze(this);
+        }
+    }
+
+    private void requestTease() {
+        if (mHost != null) {
+            mHost.requestTease(this);
+        }
+    }
+
+    private void dozingStopped() {
+        if (mHost != null) {
+            mHost.dozingStopped(this);
+        }
+    }
+
+    private void listenForTeaseSignals(boolean listen) {
+        if (DEBUG) Log.d(mTag, "listenForTeaseSignals: " + listen);
+        if (mHost == null) return;
+        listenForSignificantMotion(listen);
+        if (listen) {
+            mContext.registerReceiver(mTeaseReceiver, new IntentFilter(TEASE_ACTION));
+            mTeaseReceiverRegistered = true;
+            mHost.addCallback(mHostCallback);
+        } else {
+            if (mTeaseReceiverRegistered) {
+                mContext.unregisterReceiver(mTeaseReceiver);
+            }
+            mTeaseReceiverRegistered = false;
+            mHost.removeCallback(mHostCallback);
+        }
+    }
+
+    private void listenForSignificantMotion(boolean listen) {
+        if (mSigMotionSensor == null) return;
+        if (listen) {
+            mSensors.requestTriggerSensor(mSigMotionListener, mSigMotionSensor);
+        } else {
+            mSensors.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor);
+        }
+    }
+
+    private static String triggerEventToString(TriggerEvent event) {
+        if (event == null) return null;
+        final StringBuilder sb = new StringBuilder("TriggerEvent[")
+                .append(event.timestamp).append(',')
+                .append(event.sensor.getName());
+        if (event.values != null) {
+            for (int i = 0; i < event.values.length; i++) {
+                sb.append(',').append(event.values[i]);
+            }
+        }
+        return sb.append(']').toString();
+    }
+
+    private final TriggerEventListener mSigMotionListener = new TriggerEventListener() {
+        @Override
+        public void onTrigger(TriggerEvent event) {
+            if (DEBUG) Log.d(mTag, "sigMotion.onTrigger: " + triggerEventToString(event));
+            if (DEBUG) {
+                final Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
+                if (v != null) {
+                    v.vibrate(1000);
+                }
+            }
+            requestTease();
+            listenForSignificantMotion(true);  // reregister, this sensor only fires once
+        }
+    };
+
+    private final BroadcastReceiver mTeaseReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG) Log.d(mTag, "Received tease intent");
+            requestTease();
+        }
+    };
+
+    private final Host.Callback mHostCallback = new Host.Callback() {
+        @Override
+        public void onNewNotifications() {
+            if (DEBUG) Log.d(mTag, "onNewNotifications");
+            requestTease();
+        }
+    };
+
+    public interface Host {
+        void addCallback(Callback callback);
+        void removeCallback(Callback callback);
+        void requestDoze(DozeService dozeService);
+        void requestTease(DozeService dozeService);
+        void dozingStopped(DozeService dozeService);
+
+        public interface Callback {
+            void onNewNotifications();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 2abbad5..8995437 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -35,8 +35,6 @@
             public static final boolean EnableTaskStackClipping = true;
             // Enables tapping on the TaskBar to launch the task
             public static final boolean EnableTaskBarTouchEvents = true;
-            // Enables the use of theme colors as the task bar background
-            public static final boolean EnableTaskBarThemeColors = true;
             // Enables app-info pane on long-pressing the icon
             public static final boolean EnableDevAppInfoOnLongPress = true;
             // Enables the search bar layout
@@ -95,6 +93,8 @@
         public static class App {
             public static int AppWidgetHostId = 1024;
             public static String Key_SearchAppWidgetId = "searchAppWidgetId";
+            public static String Key_DebugModeEnabled = "debugModeEnabled";
+            public static String DebugModeVersion = "A";
         }
         public static class Window {
             // The dark background dim is set behind the empty recents view
diff --git a/packages/SystemUI/src/com/android/systemui/recents/DebugTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/DebugTrigger.java
new file mode 100644
index 0000000..d90e2be
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/DebugTrigger.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import android.os.Handler;
+import android.os.SystemClock;
+import android.view.KeyEvent;
+
+/**
+ * A trigger for catching a debug chord.
+ * We currently use volume up then volume down to trigger this mode.
+ */
+public class DebugTrigger {
+
+    Handler mHandler;
+    Runnable mTriggeredRunnable;
+
+    int mLastKeyCode;
+    long mLastKeyCodeTime;
+
+    public DebugTrigger(Runnable triggeredRunnable) {
+        mHandler = new Handler();
+        mTriggeredRunnable = triggeredRunnable;
+    }
+
+    /** Resets the debug trigger */
+    void reset() {
+        mLastKeyCode = 0;
+        mLastKeyCodeTime = 0;
+    }
+
+    /**
+     * Processes a key event and tests if it is a part of the trigger. If the chord is complete,
+     * then we just call the callback.
+     */
+    public void onKeyEvent(int keyCode) {
+        if (mLastKeyCode == 0) {
+            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+                mLastKeyCode = keyCode;
+                mLastKeyCodeTime = SystemClock.uptimeMillis();
+                return;
+            }
+        } else {
+            if (mLastKeyCode == KeyEvent.KEYCODE_VOLUME_UP &&
+                    keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+                if ((SystemClock.uptimeMillis() - mLastKeyCodeTime) < 750) {
+                    mTriggeredRunnable.run();
+                }
+            }
+        }
+        reset();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 52a17df..ecdc9dd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.ActivityOptions;
+import android.app.SearchManager;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
@@ -25,13 +26,16 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Pair;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewStub;
+import android.widget.Toast;
 import com.android.systemui.R;
+import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.FullscreenTransitionOverlayView;
@@ -109,7 +113,7 @@
     }
 
     // Broadcast receiver to handle messages from our RecentsService
-    BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
+    final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
@@ -143,18 +147,29 @@
                 mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView));
                 // Call our callback
                 onEnterAnimationTriggered();
+            } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
+                // Refresh the search widget
+                refreshSearchWidget();
             }
         }
     };
 
     // Broadcast receiver to handle messages from the system
-    BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
+    final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             mFinishWithoutAnimationRunnable.run();
         }
     };
 
+    // Debug trigger
+    final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() {
+        @Override
+        public void run() {
+            onDebugModeTriggered();
+        }
+    });
+
     /** Updates the set of recent tasks */
     void updateRecentsTasks(Intent launchIntent) {
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -431,6 +446,7 @@
         filter.addAction(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY);
         filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
         filter.addAction(RecentsService.ACTION_START_ENTER_ANIMATION);
+        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
         registerReceiver(mServiceBroadcastReceiver, filter);
 
         // Register the broadcast receiver to handle messages when the screen is turned off
@@ -513,7 +529,8 @@
             mRecentsView.focusNextTask(!backward);
             return true;
         }
-
+        // Pass through the debug trigger
+        mDebugTrigger.onKeyEvent(keyCode);
         return super.onKeyDown(keyCode, event);
     }
 
@@ -546,6 +563,23 @@
         }
     }
 
+    /** Called when debug mode is triggered */
+    public void onDebugModeTriggered() {
+        if (mConfig.developerOptionsEnabled) {
+            SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
+            if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
+                // Disable the debug mode
+                settings.edit().remove(Constants.Values.App.Key_DebugModeEnabled).apply();
+            } else {
+                // Enable the debug mode
+                settings.edit().putBoolean(Constants.Values.App.Key_DebugModeEnabled, true).apply();
+            }
+            Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion +
+                    ") toggled, please restart Recents now", Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    /** Called when the enter recents animation is triggered. */
     public void onEnterAnimationTriggered() {
         // Animate the scrims in
         mScrimViews.startEnterRecentsAnimation();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
index d55eba7..3754340 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
@@ -19,6 +19,7 @@
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
+import com.android.systemui.recents.model.RecentsTaskLoader;
 
 /** Our special app widget host for the Search widget */
 public class RecentsAppWidgetHost extends AppWidgetHost {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 10978ca..d57f779 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -103,6 +103,7 @@
 
     /** Dev options */
     public boolean developerOptionsEnabled;
+    public boolean debugModeEnabled;
 
     /** Private constructor */
     private RecentsConfiguration(Context context) {
@@ -141,10 +142,14 @@
 
     /** Updates the state, given the specified context */
     void update(Context context) {
+        SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
         Resources res = context.getResources();
         DisplayMetrics dm = res.getDisplayMetrics();
         mDisplayMetrics = dm;
 
+        // Debug mode
+        debugModeEnabled = settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false);
+
         // Animations
         animationPxMovementPerSecond =
                 res.getDimensionPixelSize(R.dimen.recents_animation_movement_in_dps_per_second);
@@ -168,7 +173,6 @@
         searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
 
         // Update the search widget id
-        SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
         searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
 
         // Task stack
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index e554af7..e40d732 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -26,6 +26,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
+import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.TaskStackView;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index c47f7d7..f7f86c4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -306,6 +306,13 @@
         }
 
         Drawable icon = info.loadIcon(mPm);
+        return getBadgedIcon(icon, userId);
+    }
+
+    /**
+     * Returns the given icon for a user, badging if necessary.
+     */
+    public Drawable getBadgedIcon(Drawable icon, int userId) {
         if (userId != UserHandle.myUserId()) {
             icon = mUm.getBadgedDrawableForUser(icon, new UserHandle(userId));
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 25875bc..6d6376f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -68,20 +68,20 @@
     }
 
     /** Calculates the luminance-preserved greyscale of a given color. */
-    private static int colorToGreyscale(int color) {
+    public static int colorToGreyscale(int color) {
         return Math.round(0.2126f * Color.red(color) + 0.7152f * Color.green(color) +
                 0.0722f * Color.blue(color));
     }
 
     /** Returns the ideal color to draw on top of a specified background color. */
-    public static int getIdealColorForBackgroundColor(int color, int lightRes, int darkRes) {
-        int greyscale = colorToGreyscale(color);
+    public static int getIdealColorForBackgroundColorGreyscale(int greyscale, int lightRes,
+                                                               int darkRes) {
         return (greyscale < 128) ? lightRes : darkRes;
     }
     /** Returns the ideal drawable to draw on top of a specified background color. */
-    public static Drawable getIdealResourceForBackgroundColor(int color, Drawable lightRes,
-                                                           Drawable darkRes) {
-        int greyscale = colorToGreyscale(color);
+    public static Drawable getIdealResourceForBackgroundColorGreyscale(int greyscale,
+                                                                       Drawable lightRes,
+                                                                       Drawable darkRes) {
         return (greyscale < 128) ? lightRes : darkRes;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java
new file mode 100644
index 0000000..1344729
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java
@@ -0,0 +1,34 @@
+/*
+ * 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.model;
+
+import android.graphics.Bitmap;
+
+/**
+ * The Bitmap LRU cache.
+ */
+class BitmapLruCache extends KeyStoreLruCache<Bitmap> {
+    public BitmapLruCache(int cacheSize) {
+        super(cacheSize);
+    }
+
+    @Override
+    protected int computeSize(Bitmap b) {
+        // The cache size will be measured in kilobytes rather than number of items
+        return b.getAllocationByteCount() / 1024;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java
new file mode 100644
index 0000000..61d19da
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java
@@ -0,0 +1,36 @@
+/*
+ * 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.model;
+
+import android.graphics.drawable.Drawable;
+
+/**
+ * The Drawable LRU cache.
+ */
+class DrawableLruCache extends KeyStoreLruCache<Drawable> {
+    public DrawableLruCache(int cacheSize) {
+        super(cacheSize);
+    }
+
+    @Override
+    protected int computeSize(Drawable d) {
+        // The cache size will be measured in kilobytes rather than number of items
+        // NOTE: this isn't actually correct, as the icon may be smaller
+        int maxBytes = (d.getIntrinsicWidth() * d.getIntrinsicHeight() * 4);
+        return maxBytes / 1024;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java
new file mode 100644
index 0000000..3ccca9a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.model;
+
+import android.util.LruCache;
+
+import java.util.HashMap;
+
+/**
+ * An LRU cache that support querying the keys as well as values. By using the Task's key, we can
+ * prevent holding onto a reference to the Task resource data, while keeping the cache data in
+ * memory where necessary.
+ */
+public class KeyStoreLruCache<V> {
+    // We keep a set of keys that are associated with the LRU cache, so that we can find out
+    // information about the Task that was previously in the cache.
+    HashMap<Task.TaskKey, Task.TaskKey> mKeys = new HashMap<Task.TaskKey, Task.TaskKey>();
+    // The cache implementation
+    LruCache<Task.TaskKey, V> mCache;
+
+    public KeyStoreLruCache(int cacheSize) {
+        mCache = new LruCache<Task.TaskKey, V>(cacheSize) {
+            @Override
+            protected int sizeOf(Task.TaskKey t, V v) {
+                return computeSize(v);
+            }
+
+            @Override
+            protected void entryRemoved(boolean evicted, Task.TaskKey key, V oldV, V newV) {
+                mKeys.remove(key);
+            }
+        };
+    }
+
+    /** Computes the size of a value. */
+    protected int computeSize(V value) {
+        return 0;
+    }
+
+    /** Gets a specific entry in the cache. */
+    final V get(Task.TaskKey key) {
+        return mCache.get(key);
+    }
+
+    /**
+     * Returns the value only if the last active time of the key currently in the lru cache is
+     * greater than or equal to the last active time of the key specified.
+     */
+    final V getCheckLastActiveTime(Task.TaskKey key) {
+        Task.TaskKey lruKey = mKeys.get(key);
+        if (lruKey != null && (lruKey.lastActiveTime < key.lastActiveTime)) {
+            // The task has changed (been made active since the last time it was put into the
+            // LRU cache) so invalidate that item in the cache
+            remove(lruKey);
+            return null;
+        }
+        // Either the task does not exist in the cache, or the last active time is the same as
+        // the key specified
+        return mCache.get(key);
+    }
+
+    /** Gets the previous task key that matches the specified key. */
+    final Task.TaskKey getKey(Task.TaskKey key) {
+        return mKeys.get(key);
+    }
+
+    /** Puts an entry in the cache for a specific key. */
+    final void put(Task.TaskKey key, V value) {
+        mCache.put(key, value);
+        if (mKeys.containsKey(key)) {
+            mKeys.get(key).updateLastActiveTime(key.lastActiveTime);
+        } else {
+            mKeys.put(key, key);
+        }
+    }
+
+    /** Removes a cache entry for a specific key. */
+    final void remove(Task.TaskKey key) {
+        mCache.remove(key);
+        mKeys.remove(key);
+    }
+
+    /** Removes all the entries in the cache. */
+    final void evictAll() {
+        mCache.evictAll();
+        mKeys.clear();
+    }
+
+    /** Returns the size of the cache. */
+    final int size() {
+        return mCache.size();
+    }
+
+    /** Trims the cache to a specific size */
+    final void trimToSize(int cacheSize) {
+        mCache.resize(cacheSize);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
rename to packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
index 04d1f1f..cbe39e3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents;
+package com.android.systemui.recents.model;
 
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Looper;
 import com.android.internal.content.PackageMonitor;
+import com.android.systemui.recents.SystemServicesProxy;
 
 import java.util.HashSet;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
rename to packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 07a6a56..15f4a76 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents;
+package com.android.systemui.recents.model;
 
 import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
@@ -27,11 +27,11 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.UserHandle;
-import android.util.LruCache;
 import android.util.Pair;
-import com.android.systemui.recents.model.SpaceNode;
-import com.android.systemui.recents.model.Task;
-import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.Console;
+import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.SystemServicesProxy;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -204,8 +204,8 @@
                 final Task t = nextTaskData.first;
                 final boolean forceLoadTask = nextTaskData.second;
                 if (t != null) {
-                    Drawable loadIcon = mApplicationIconCache.get(t.key);
-                    Bitmap loadThumbnail = mThumbnailCache.get(t.key);
+                    Drawable loadIcon = mApplicationIconCache.getCheckLastActiveTime(t.key);
+                    Bitmap loadThumbnail = mThumbnailCache.getCheckLastActiveTime(t.key);
                     if (Console.Enabled) {
                         Console.log(Constants.Log.App.TaskDataLoader,
                                 "  [TaskResourceLoader|load]",
@@ -255,7 +255,7 @@
                         mMainThreadHandler.post(new Runnable() {
                             @Override
                             public void run() {
-                                t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
+                                t.notifyTaskDataLoaded(newThumbnail, newIcon);
                             }
                         });
                     }
@@ -282,40 +282,6 @@
     }
 }
 
-/**
- * The drawable cache.  By using the Task's key, we can prevent holding onto a reference to the Task
- * resource data, while keeping the cache data in memory where necessary.
- */
-class DrawableLruCache extends LruCache<Task.TaskKey, Drawable> {
-    public DrawableLruCache(int cacheSize) {
-        super(cacheSize);
-    }
-
-    @Override
-    protected int sizeOf(Task.TaskKey t, Drawable d) {
-        // The cache size will be measured in kilobytes rather than number of items
-        // NOTE: this isn't actually correct, as the icon may be smaller
-        int maxBytes = (d.getIntrinsicWidth() * d.getIntrinsicHeight() * 4);
-        return maxBytes / 1024;
-    }
-}
-
-/**
- * The bitmap cache.  By using the Task's key, we can prevent holding onto a reference to the Task
- * resource data, while keeping the cache data in memory where necessary.
- */
-class BitmapLruCache extends LruCache<Task.TaskKey, Bitmap> {
-    public BitmapLruCache(int cacheSize) {
-        super(cacheSize);
-    }
-
-    @Override
-    protected int sizeOf(Task.TaskKey t, Bitmap bitmap) {
-        // The cache size will be measured in kilobytes rather than number of items
-        return bitmap.getAllocationByteCount() / 1024;
-    }
-}
-
 /* Recents task loader
  * NOTE: We should not hold any references to a Context from a static instance */
 public class RecentsTaskLoader {
@@ -417,12 +383,13 @@
     }
 
     /** Reload the set of recent tasks */
-    SpaceNode reload(Context context, int preloadCount) {
+    public SpaceNode reload(Context context, int preloadCount) {
         long t1 = System.currentTimeMillis();
 
         if (Console.Enabled) {
             Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
         }
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
         Resources res = context.getResources();
         ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
         TaskStack stack = new TaskStack(context);
@@ -443,11 +410,12 @@
 
             ActivityManager.TaskDescription av = t.taskDescription;
             String activityLabel = null;
-            BitmapDrawable activityIcon = null;
-            int activityColor = 0;
+            Drawable activityIcon = null;
+            int activityColor = config.taskBarViewDefaultBackgroundColor;
             if (av != null) {
                 activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info));
-                activityIcon = (av.getIcon() != null) ? new BitmapDrawable(res, av.getIcon()) : null;
+                activityIcon = (av.getIcon() != null) ?
+                        ssp.getBadgedIcon(new BitmapDrawable(res, av.getIcon()), t.userId) : null;
                 activityColor = av.getPrimaryColor();
             } else {
                 activityLabel = ssp.getActivityLabel(info);
@@ -456,7 +424,7 @@
 
             // Create a new task
             Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, activityLabel,
-                    activityIcon, activityColor, t.userId);
+                    activityIcon, activityColor, t.userId, t.lastActiveTime);
 
             // Preload the specified number of apps
             if (i >= (taskCount - preloadCount)) {
@@ -466,45 +434,44 @@
                             "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
                 }
 
-                // Load the icon (if possible and not the foremost task, from the cache)
-                if (!isForemostTask) {
-                    task.applicationIcon = mApplicationIconCache.get(task.key);
-                    if (task.applicationIcon != null) {
-                        // Even though we get things from the cache, we should update them
-                        // if they've changed in the bg
-                        tasksToForceLoad.add(task);
-                    }
-                }
+                // Load the icon from the cache if possible
+                task.applicationIcon = mApplicationIconCache.getCheckLastActiveTime(task.key);
                 if (task.applicationIcon == null) {
-                    task.applicationIcon = ssp.getActivityIcon(info, task.userId);
-                    if (task.applicationIcon != null) {
-                        mApplicationIconCache.put(task.key, task.applicationIcon);
+                    if (isForemostTask) {
+                        // We force loading the application icon for the foremost task
+                        task.applicationIcon = ssp.getActivityIcon(info, task.userId);
+                        if (task.applicationIcon != null) {
+                            mApplicationIconCache.put(task.key, task.applicationIcon);
+                        } else {
+                            task.applicationIcon = mDefaultApplicationIcon;
+                        }
                     } else {
-                        task.applicationIcon = mDefaultApplicationIcon;
+                        // Either the task has updated, or we haven't cached any information for the
+                        // task, so reload it
+                        tasksToForceLoad.add(task);
                     }
                 }
 
                 // Load the thumbnail (if possible and not the foremost task, from the cache)
-                if (!isForemostTask) {
-                    task.thumbnail = mThumbnailCache.get(task.key);
-                    if (task.thumbnail != null && !tasksToForceLoad.contains(task)) {
-                        // Even though we get things from the cache, we should update them if
-                        // they've changed in the bg
-                        tasksToForceLoad.add(task);
-                    }
-                }
+                task.thumbnail = mThumbnailCache.getCheckLastActiveTime(task.key);
                 if (task.thumbnail == null) {
                     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);
-                        mThumbnailCache.put(task.key, task.thumbnail);
+                    if (isForemostTask) {
+                        // We force loading the thumbnail icon for the foremost task
+                        task.thumbnail = ssp.getTaskThumbnail(task.key.id);
+                        if (task.thumbnail != null) {
+                            task.thumbnail.setHasAlpha(false);
+                            mThumbnailCache.put(task.key, task.thumbnail);
+                        } else {
+                            task.thumbnail = mDefaultThumbnail;
+                        }
                     } else {
-                        task.thumbnail = mDefaultThumbnail;
+                        // Either the task has updated, or we haven't cached any information for the
+                        // task, so reload it
+                        tasksToForceLoad.add(task);
                     }
                 }
             }
@@ -536,7 +503,7 @@
         return root;
     }
 
-    /** Acquires the task resource data from the pool. */
+    /** Acquires the task resource data directly from the pool. */
     public void loadTaskData(Task t) {
         Drawable applicationIcon = mApplicationIconCache.get(t.key);
         Bitmap thumbnail = mThumbnailCache.get(t.key);
@@ -559,7 +526,7 @@
         if (requiresLoad) {
             mLoadQueue.addTask(t, false);
         }
-        t.notifyTaskDataLoaded(thumbnail, applicationIcon, false);
+        t.notifyTaskDataLoaded(thumbnail, applicationIcon);
     }
 
     /** Releases the task resource data back into the pool. */
@@ -613,7 +580,7 @@
      * Handles signals from the system, trimming memory when requested to prevent us from running
      * out of memory.
      */
-    void onTrimMemory(int level) {
+    public void onTrimMemory(int level) {
         if (Console.Enabled) {
             Console.log(Constants.Log.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
                     Console.trimMemoryLevelToString(level));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index f366ef0..abfb221 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -16,11 +16,10 @@
 
 package com.android.systemui.recents.model;
 
-import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import com.android.systemui.recents.Utilities;
 
 
 /**
@@ -30,7 +29,7 @@
     /* Task callbacks */
     public interface TaskCallbacks {
         /* Notifies when a task has been bound */
-        public void onTaskDataLoaded(boolean reloadingTaskData);
+        public void onTaskDataLoaded();
         /* Notifies when a task has been unbound */
         public void onTaskDataUnloaded();
     }
@@ -40,11 +39,17 @@
         public final int id;
         public final Intent baseIntent;
         public final int userId;
+        public long lastActiveTime;
 
-        public TaskKey(int id, Intent intent, int userId) {
+        public TaskKey(int id, Intent intent, int userId, long lastActiveTime) {
             this.id = id;
             this.baseIntent = intent;
             this.userId = userId;
+            this.lastActiveTime = lastActiveTime;
+        }
+
+        public void updateLastActiveTime(long lastActiveTime) {
+            this.lastActiveTime = lastActiveTime;
         }
 
         @Override
@@ -64,7 +69,8 @@
         @Override
         public String toString() {
             return "Task.Key: " + id + ", "
-                    + "u" + userId + ", "
+                    + "u: " + userId + ", "
+                    + "lat: " + lastActiveTime + ", "
                     + baseIntent.getComponent().getPackageName();
         }
     }
@@ -74,6 +80,7 @@
     public Drawable activityIcon;
     public String activityLabel;
     public int colorPrimary;
+    public int colorPrimaryGreyscale;
     public Bitmap thumbnail;
     public boolean isActive;
     public int userId;
@@ -85,11 +92,12 @@
     }
 
     public Task(int id, boolean isActive, Intent intent, String activityTitle,
-                BitmapDrawable activityIcon, int colorPrimary, int userId) {
-        this.key = new TaskKey(id, intent, userId);
+                Drawable activityIcon, int colorPrimary, int userId, long lastActiveTime) {
+        this.key = new TaskKey(id, intent, userId, lastActiveTime);
         this.activityLabel = activityTitle;
         this.activityIcon = activityIcon;
         this.colorPrimary = colorPrimary;
+        this.colorPrimaryGreyscale = Utilities.colorToGreyscale(colorPrimary);
         this.isActive = isActive;
         this.userId = userId;
     }
@@ -100,12 +108,11 @@
     }
 
     /** Notifies the callback listeners that this task has been loaded */
-    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon,
-                                     boolean reloadingTaskData) {
+    public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon) {
         this.applicationIcon = applicationIcon;
         this.thumbnail = thumbnail;
         if (mCb != null) {
-            mCb.onTaskDataLoaded(reloadingTaskData);
+            mCb.onTaskDataLoaded();
         }
     }
 
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 8afc5b9..3856311 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.UserHandle;
@@ -36,8 +37,8 @@
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.RecentsPackageMonitor;
-import com.android.systemui.recents.RecentsTaskLoader;
+import com.android.systemui.recents.model.RecentsPackageMonitor;
+import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
@@ -60,6 +61,7 @@
 
     RecentsConfiguration mConfig;
     LayoutInflater mInflater;
+    Paint mDebugModePaint;
 
     // The space partitioning root of this container
     SpaceNode mBSP;
@@ -107,6 +109,15 @@
             addView(stackView);
             mHasTasks |= (stack.getTaskCount() > 0);
         }
+
+        // Enable debug mode drawing
+        if (mConfig.debugModeEnabled) {
+            mDebugModePaint = new Paint();
+            mDebugModePaint.setColor(0xFFff0000);
+            mDebugModePaint.setStyle(Paint.Style.STROKE);
+            mDebugModePaint.setStrokeWidth(5f);
+            setWillNotDraw(false);
+        }
     }
 
     /** Launches the focused task from the first stack if possible */
@@ -322,6 +333,29 @@
         }
     }
 
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        // Debug mode drawing
+        if (mConfig.debugModeEnabled) {
+            canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mDebugModePaint);
+        }
+    }
+
+    @Override
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        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
+        mConfig.updateSystemInsets(insets.getSystemWindowInsets());
+        requestLayout();
+
+        return insets.consumeSystemWindowInsets(false, false, false, true);
+    }
+
     /** Notifies each task view of the user interaction. */
     public void onUserInteraction() {
         // Get the first stack view
@@ -354,29 +388,6 @@
         }
     }
 
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        if (Console.Enabled) {
-            Console.log(Constants.Log.UI.Draw, "[RecentsView|dispatchDraw]", "",
-                    Console.AnsiPurple);
-        }
-        super.dispatchDraw(canvas);
-    }
-
-    @Override
-    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        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
-        mConfig.updateSystemInsets(insets.getSystemWindowInsets());
-        requestLayout();
-
-        return insets.consumeSystemWindowInsets(false, false, false, true);
-    }
-
     /** Unfilters any filtered stacks */
     public boolean unfilterFilteredStacks() {
         if (mBSP != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index 80f804d..2c0dea3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -90,11 +90,11 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (Constants.DebugFlags.App.EnableTaskBarTouchEvents) {
-            return super.onTouchEvent(event);
-        }
         // We ignore taps on the task bar except on the filter and dismiss buttons
-        return true;
+        if (!Constants.DebugFlags.App.EnableTaskBarTouchEvents) return true;
+        if (mConfig.debugModeEnabled) return true;
+
+        return super.onTouchEvent(event);
     }
 
     @Override
@@ -149,7 +149,7 @@
     }
 
     /** Binds the bar view to the task */
-    void rebindToTask(Task t, boolean animate) {
+    void rebindToTask(Task t) {
         mTask = t;
         // If an activity icon is defined, then we use that as the primary icon to show in the bar,
         // otherwise, we fall back to the application icon
@@ -160,15 +160,12 @@
         }
         mActivityDescription.setText(t.activityLabel);
         // Try and apply the system ui tint
-        int tint = t.colorPrimary;
-        if (!Constants.DebugFlags.App.EnableTaskBarThemeColors || tint == 0) {
-            tint = mConfig.taskBarViewDefaultBackgroundColor;
-        }
-        setBackgroundColor(tint);
-        mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColor(tint,
-                mConfig.taskBarViewLightTextColor, mConfig.taskBarViewDarkTextColor));
-        mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColor(tint,
-                mLightDismissDrawable, mDarkDismissDrawable));
+        setBackgroundColor(t.colorPrimary);
+        mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColorGreyscale(
+                t.colorPrimaryGreyscale, mConfig.taskBarViewLightTextColor,
+                mConfig.taskBarViewDarkTextColor));
+        mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColorGreyscale(
+                t.colorPrimaryGreyscale, mLightDismissDrawable, mDarkDismissDrawable));
     }
 
     /** Unbinds the bar view from the task */
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 1cf28b9..452665a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -36,10 +36,10 @@
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.DozeTrigger;
 import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.RecentsPackageMonitor;
-import com.android.systemui.recents.RecentsTaskLoader;
 import com.android.systemui.recents.ReferenceCountedTrigger;
 import com.android.systemui.recents.Utilities;
+import com.android.systemui.recents.model.RecentsPackageMonitor;
+import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 
@@ -935,6 +935,11 @@
         mUIDozeTrigger.poke();
     }
 
+    /** Disables handling touch on this task view. */
+    void setTouchOnTaskView(TaskView tv, boolean enabled) {
+        tv.setOnClickListener(enabled ? this : null);
+    }
+
     /**** TaskStackCallbacks Implementation ****/
 
     @Override
@@ -1177,47 +1182,34 @@
     @Override
     public void prepareViewToEnterPool(TaskView tv) {
         Task task = tv.getTask();
-        tv.resetViewProperties();
         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();
-        loader.unloadTaskData(task);
+        RecentsTaskLoader.getInstance().unloadTaskData(task);
 
         // Detach the view from the hierarchy
         detachViewFromParent(tv);
 
-        // Disable hw layers on this view
+        // Disable HW layers
         tv.disableHwLayers();
+
+        // Reset the view properties
+        tv.resetViewProperties();
     }
 
     @Override
-    public void prepareViewToLeavePool(TaskView tv, Task prepareData, boolean isNewView) {
+    public void prepareViewToLeavePool(TaskView tv, Task task, boolean 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;
-        // We try and rebind the task (this MUST be done before the task filled)
+        // Rebind the task and request that this task's data be filled into the TaskView
         tv.onTaskBound(task);
-        // Request that this tasks's data be filled
-        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
-        loader.loadTaskData(task);
-        // Find the index where this task should be placed in the children
-        int insertIndex = -1;
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            Task tvTask = ((TaskView) getChildAt(i)).getTask();
-            if (mStack.containsTask(task) && (mStack.indexOfTask(task) < mStack.indexOfTask(tvTask))) {
-                insertIndex = i;
-                break;
-            }
-        }
+        RecentsTaskLoader.getInstance().loadTaskData(task);
 
         // Sanity check, the task view should always be clipping against the stack at this point,
         // but just in case, re-enable it here
@@ -1228,6 +1220,20 @@
             tv.setNoUserInteractionState();
         }
 
+        // Find the index where this task should be placed in the stack
+        int insertIndex = -1;
+        int taskIndex = mStack.indexOfTask(task);
+        if (taskIndex != -1) {
+            int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                Task tvTask = ((TaskView) getChildAt(i)).getTask();
+                if (taskIndex < mStack.indexOfTask(tvTask)) {
+                    insertIndex = i;
+                    break;
+                }
+            }
+        }
+
         // Add/attach the view to the hierarchy
         if (Console.Enabled) {
             Console.log(Constants.Log.ViewPool.PoolCallbacks, "  [TaskStackView|insertIndex]",
@@ -1237,7 +1243,7 @@
             addView(tv, insertIndex);
 
             // Set the callbacks and listeners for this new view
-            tv.setOnClickListener(this);
+            setTouchOnTaskView(tv, true);
             tv.setCallbacks(this);
         } else {
             attachViewToParent(tv, insertIndex, tv.getLayoutParams());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index d2f18ae..f9c5f13 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -371,11 +371,13 @@
 
     @Override
     public void onBeginDrag(View v) {
-        // Enable HW layers
-        mSv.addHwLayersRefCount("swipeBegin");
-        // Disable clipping with the stack while we are swiping
         TaskView tv = (TaskView) v;
+        // Disable clipping with the stack while we are swiping
         tv.setClipViewInStack(false);
+        // Enable HW layers on that task
+        tv.enableHwLayers();
+        // Disallow touch events from this task view
+        mSv.setTouchOnTaskView(tv, false);
         // Disallow parents from intercepting touch events
         final ViewParent parent = mSv.getParent();
         if (parent != null) {
@@ -391,25 +393,31 @@
     @Override
     public void onChildDismissed(View v) {
         TaskView tv = (TaskView) v;
-        mSv.onTaskDismissed(tv);
-
+        // Disable HW layers on that task
+        if (mSv.mHwLayersTrigger.getCount() == 0) {
+            tv.disableHwLayers();
+        }
         // Re-enable clipping with the stack (we will reuse this view)
         tv.setClipViewInStack(true);
-
-        // Disable HW layers
-        mSv.decHwLayersRefCount("swipeComplete");
+        // Remove the task view from the stack
+        mSv.onTaskDismissed(tv);
     }
 
     @Override
     public void onSnapBackCompleted(View v) {
-        // Re-enable clipping with the stack
-        TaskView tv = (TaskView) v;
-        tv.setClipViewInStack(true);
+        onDragCancelled(v);
     }
 
     @Override
     public void onDragCancelled(View v) {
-        // Disable HW layers
-        mSv.decHwLayersRefCount("swipeCancelled");
+        TaskView tv = (TaskView) v;
+        // Disable HW layers on that task
+        if (mSv.mHwLayersTrigger.getCount() == 0) {
+            tv.disableHwLayers();
+        }
+        // Re-enable clipping with the stack
+        tv.setClipViewInStack(true);
+        // Re-enable touch events from this task view
+        mSv.setTouchOnTaskView(tv, true);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
index c2b2094..636746d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
@@ -83,7 +83,7 @@
     }
 
     /** Binds the thumbnail view to the task */
-    void rebindToTask(Task t, boolean animate) {
+    void rebindToTask(Task t) {
         mTask = t;
         if (t.thumbnail != null) {
             setImageBitmap(t.thumbnail);
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 cfba74c..f9d5a65 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -123,7 +123,7 @@
         mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
 
         if (mTaskDataLoaded) {
-            onTaskDataLoaded(false);
+            onTaskDataLoaded();
         }
     }
 
@@ -551,11 +551,11 @@
     }
 
     @Override
-    public void onTaskDataLoaded(boolean reloadingTaskData) {
+    public void onTaskDataLoaded() {
         if (mThumbnailView != null && mBarView != null) {
             // Bind each of the views to the new task data
-            mThumbnailView.rebindToTask(mTask, reloadingTaskData);
-            mBarView.rebindToTask(mTask, reloadingTaskData);
+            mThumbnailView.rebindToTask(mTask);
+            mBarView.rebindToTask(mTask);
             // Rebind any listeners
             mBarView.mApplicationIcon.setOnClickListener(this);
             mBarView.mDismissButton.setOnClickListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index f6f78e9..1550217 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -25,6 +25,8 @@
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
@@ -89,6 +91,8 @@
             = new PathInterpolator(0, 0, 0.5f, 1);
 
     private boolean mDimmed;
+    private boolean mDark;
+    private final Paint mDarkPaint = createDarkPaint();
 
     private int mBgResId = com.android.internal.R.drawable.notification_material_bg;
     private int mDimmedBgResId = com.android.internal.R.drawable.notification_material_bg_dim;
@@ -295,6 +299,34 @@
         }
     }
 
+    public void setDark(boolean dark, boolean fade) {
+        // TODO implement fade
+        if (mDark != dark) {
+            mDark = dark;
+            if (mDark) {
+                setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
+            } else {
+                setLayerType(View.LAYER_TYPE_NONE, null);
+            }
+        }
+    }
+
+    private static Paint createDarkPaint() {
+        final Paint p = new Paint();
+        final float[] invert = {
+            -1f,  0f,  0f, 1f, 1f,
+             0f, -1f,  0f, 1f, 1f,
+             0f,  0f, -1f, 1f, 1f,
+             0f,  0f,  0f, 1f, 0f
+        };
+        final ColorMatrix m = new ColorMatrix(invert);
+        final ColorMatrix grayscale = new ColorMatrix();
+        grayscale.setSaturation(0);
+        m.preConcat(grayscale);
+        p.setColorFilter(new ColorMatrixColorFilter(m));
+        return p;
+    }
+
     /**
      * Sets the resource id for the background of this notification.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 4d4a8ab..c3fb83c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -167,6 +167,15 @@
     }
 
     /**
+     * Sets the notification as dark. The default implementation does nothing.
+     *
+     * @param dark Whether the notification should be dark.
+     * @param fade Whether an animation should be played to change the state.
+     */
+    public void setDark(boolean dark, boolean fade) {
+    }
+
+    /**
      * @return The desired notification height.
      */
     public int getIntrinsicHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c684c9f..cec7592 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -109,7 +109,6 @@
             new KeyguardClockPositionAlgorithm();
     private KeyguardClockPositionAlgorithm.Result mClockPositionResult =
             new KeyguardClockPositionAlgorithm.Result();
-    private boolean mIsSwipedHorizontally;
     private boolean mIsExpanding;
 
     private boolean mBlockTouches;
@@ -122,18 +121,7 @@
     }
 
     public void setStatusBar(PhoneStatusBar bar) {
-        if (mStatusBar != null) {
-            mStatusBar.setOnFlipRunnable(null);
-        }
         mStatusBar = bar;
-        if (bar != null) {
-            mStatusBar.setOnFlipRunnable(new Runnable() {
-                @Override
-                public void run() {
-                    requestPanelHeightUpdate();
-                }
-            });
-        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 00951b2..62ac54e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -64,7 +64,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.provider.Settings.Global;
 import android.provider.Settings.SettingNotFoundException;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
@@ -100,6 +99,7 @@
 import com.android.systemui.DemoMode;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
+import com.android.systemui.doze.DozeService;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.qs.CircularClipper;
 import com.android.systemui.qs.QSPanel;
@@ -168,11 +168,6 @@
     private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService
     private static final int HIDE_ICONS_BELOW_SCORE = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
 
-    /**
-     * Default value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
-     */
-    private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
-
     private static final int STATUS_OR_NAV_TRANSIENT =
             View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
     private static final long AUTOHIDE_TIMEOUT_MS = 3000;
@@ -185,21 +180,6 @@
      */
     private static final int HINT_RESET_DELAY_MS = 1200;
 
-    // fling gesture tuning parameters, scaled to display density
-    private float mSelfExpandVelocityPx; // classic value: 2000px/s
-    private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
-    private float mFlingExpandMinVelocityPx; // classic value: 200px/s
-    private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
-    private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
-    private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
-    private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
-
-    private float mExpandAccelPx; // classic value: 2000px/s/s
-    private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
-
-    private float mFlingGestureMaxOutputVelocityPx; // how fast can it really go? (should be a little
-                                                    // faster than mSelfCollapseVelocityPx)
-
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
@@ -225,6 +205,7 @@
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
     private StatusBarWindowManager mStatusBarWindowManager;
     private UnlockMethodCache mUnlockMethodCache;
+    private DozeServiceHost mDozeServiceHost;
 
     int mPixelFormat;
     Object mQueueLock = new Object();
@@ -397,14 +378,9 @@
             }
         }};
 
-    private Runnable mOnFlipRunnable;
-    private VelocityTracker mSettingsTracker;
-    private float mSettingsDownY;
-    private boolean mSettingsStarted;
-    private boolean mSettingsCancelled;
-    private boolean mSettingsClosing;
     private boolean mVisible;
     private boolean mWaitingForKeyguardExit;
+    private boolean mDozing;
 
     private Interpolator mLinearOutSlowIn;
     private Interpolator mAlphaOut = new PathInterpolator(0f, 0.4f, 1f, 1f);
@@ -420,14 +396,12 @@
 
     private int mDisabledUnmodified;
 
-    public void setOnFlipRunnable(Runnable onFlipRunnable) {
-        mOnFlipRunnable = onFlipRunnable;
-    }
-
     /** Keys of notifications currently visible to the user. */
     private final ArraySet<String> mCurrentlyVisibleNotifications = new ArraySet<String>();
     private long mLastVisibilityReportUptimeMs;
 
+    private final ShadeUpdates mShadeUpdates = new ShadeUpdates();
+
     private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD
             | ViewState.LOCATION_TOP_STACK_PEEKING
             | ViewState.LOCATION_MAIN_AREA
@@ -537,6 +511,9 @@
         }
         mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
         startKeyguard();
+
+        mDozeServiceHost = new DozeServiceHost();
+        putComponent(DozeService.Host.class, mDozeServiceHost);
     }
 
     // ================================================================================
@@ -1232,7 +1209,6 @@
         for (View remove : toRemove) {
             mStackScroller.removeView(remove);
         }
-
         for (int i=0; i<toShow.size(); i++) {
             View v = toShow.get(i);
             if (v.getParent() == null) {
@@ -1265,6 +1241,7 @@
         updateRowStates();
         updateSpeedbump();
         mNotificationPanel.setQsExpansionEnabled(provisioned && mUserSetup);
+        mShadeUpdates.check();
     }
 
     private void updateSpeedbump() {
@@ -1627,10 +1604,6 @@
         }
     }
 
-    private Handler getHandler() {
-        return mHandler;
-    }
-
     View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
         public void onFocusChange(View v, boolean hasFocus) {
             // Because 'v' is a ViewGroup, all its children will be (un)selected
@@ -1775,12 +1748,6 @@
         if (false) postStartTracing();
     }
 
-    private static void cancelAnim(Animator anim) {
-        if (anim != null) {
-            anim.cancel();
-        }
-    }
-
     public void flipToNotifications(boolean animate) {
         // TODO: Animation
         mNotificationPanel.closeQs();
@@ -2273,6 +2240,7 @@
         pw.println(windowStateToString(mStatusBarWindowState));
         pw.print("  mStatusBarMode=");
         pw.println(BarTransitions.modeToString(mStatusBarMode));
+        pw.print("  mDozing="); pw.println(mDozing);
         pw.print("  mZenMode=");
         pw.println(Settings.Global.zenModeToString(mZenMode));
         pw.print("  mUseHeadsUp=");
@@ -2407,28 +2375,6 @@
         }
     }
 
-    private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
-        public void onClick(View v) {
-            synchronized (mNotificationData) {
-                mPostCollapseCleanup = new Runnable() {
-                    @Override
-                    public void run() {
-                        if (DEBUG) {
-                            Log.v(TAG, "running post-collapse cleanup");
-                        }
-                        try {
-                            mBarService.onClearAllNotifications(mCurrentUserId);
-                        } catch (Exception ex) { }
-                    }
-                };
-
-                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
-                return;
-                // TODO: Handle this better with notification stack scroller
-            }
-        }
-    };
-
     public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned) {
         if (onlyProvisioned && !isDeviceProvisioned()) return;
 
@@ -2456,12 +2402,6 @@
         }
     };
 
-    private View.OnClickListener mNotificationButtonListener = new View.OnClickListener() {
-        public void onClick(View v) {
-            animateExpandNotificationsPanel();
-        }
-    };
-
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
             if (DEBUG) Log.v(TAG, "onReceive: " + intent);
@@ -2595,21 +2535,6 @@
 
         mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
 
-        mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
-        mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
-        mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
-        mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
-
-        mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
-        mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
-
-        mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
-        mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
-
-        mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
-
-        mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
-
         mNotificationPanelGravity = res.getInteger(R.integer.notification_panel_layout_gravity);
         if (mNotificationPanelGravity <= 0) {
             mNotificationPanelGravity = Gravity.START | Gravity.TOP;
@@ -2675,7 +2600,6 @@
         if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
             return;
         }
-
         String[] newlyVisibleAr = newlyVisible.toArray(new String[newlyVisible.size()]);
         String[] noLongerVisibleAr = noLongerVisible.toArray(new String[noLongerVisible.size()]);
         try {
@@ -2950,6 +2874,7 @@
             mNotificationPanel.setKeyguardShowing(false);
             mScrimController.setKeyguardShowing(false);
         }
+        updateDozingState();
         updateStackScrollerState();
         updatePublicMode();
         updateNotifications();
@@ -2957,6 +2882,26 @@
         updateCarrierLabelVisibility(false);
     }
 
+    private void updateDozingState() {
+        final boolean bottomGone = mKeyguardBottomArea.getVisibility() == View.GONE;
+        if (mDozing) {
+            mNotificationPanel.setBackgroundColor(0xff000000);
+            mHeader.setVisibility(View.INVISIBLE);
+            if (!bottomGone) {
+                mKeyguardBottomArea.setVisibility(View.INVISIBLE);
+            }
+            mStackScroller.setDark(true, false /*animate*/);
+        } else {
+            mNotificationPanel.setBackground(null);
+            mHeader.setVisibility(View.VISIBLE);
+            if (!bottomGone) {
+                mKeyguardBottomArea.setVisibility(View.VISIBLE);
+            }
+            mStackScroller.setDark(false, false /*animate*/);
+        }
+        mScrimController.setDozing(mDozing);
+    }
+
     public void updateStackScrollerState() {
         if (mStackScroller == null) return;
         boolean onKeyguard = mState == StatusBarState.KEYGUARD;
@@ -3229,4 +3174,121 @@
         }
         notifyUiVisibilityChanged(mSystemUiVisibility);
     }
+
+    private final class ShadeUpdates {
+        private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
+        private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
+
+        public void check() {
+            mNewVisibleNotifications.clear();
+            for (int i = 0; i < mNotificationData.size(); i++) {
+                final Entry entry = mNotificationData.get(i);
+                final boolean visible = entry.row != null
+                        && entry.row.getVisibility() == View.VISIBLE;
+                if (visible) {
+                    mNewVisibleNotifications.add(entry.key + entry.notification.getPostTime());
+                }
+            }
+            final boolean updates = !mVisibleNotifications.containsAll(mNewVisibleNotifications);
+            mVisibleNotifications.clear();
+            mVisibleNotifications.putAll(mNewVisibleNotifications);
+
+            // We have new notifications
+            if (updates && mDozeServiceHost != null) {
+                mDozeServiceHost.fireNewNotifications();
+            }
+        }
+    }
+
+    private final class DozeServiceHost implements DozeService.Host {
+        // Amount of time to allow to update the time shown on the screen before releasing
+        // the wakelock.  This timeout is design to compensate for the fact that we don't
+        // currently have a way to know when time display contents have actually been
+        // refreshed once we've finished rendering a new frame.
+        private static final long PROCESSING_TIME = 500;
+
+        private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+        private final H mHandler = new H();
+
+        private DozeService mCurrentDozeService;
+
+        public void fireNewNotifications() {
+            for (Callback callback : mCallbacks) {
+                callback.onNewNotifications();
+            }
+        }
+
+        @Override
+        public void addCallback(Callback callback) {
+            mCallbacks.add(callback);
+        }
+
+        @Override
+        public void removeCallback(Callback callback) {
+            mCallbacks.remove(callback);
+        }
+
+        @Override
+        public void requestDoze(DozeService dozeService) {
+            if (dozeService == null) return;
+            dozeService.stayAwake(PROCESSING_TIME);
+            mHandler.obtainMessage(H.REQUEST_DOZE, dozeService).sendToTarget();
+        }
+
+        @Override
+        public void requestTease(DozeService dozeService) {
+            if (dozeService == null) return;
+            dozeService.stayAwake(PROCESSING_TIME);
+            mHandler.obtainMessage(H.REQUEST_TEASE, dozeService).sendToTarget();
+        }
+
+        @Override
+        public void dozingStopped(DozeService dozeService) {
+            if (dozeService == null) return;
+            dozeService.stayAwake(PROCESSING_TIME);
+            mHandler.obtainMessage(H.DOZING_STOPPED, dozeService).sendToTarget();
+        }
+
+        private void handleRequestDoze(DozeService dozeService) {
+            mCurrentDozeService = dozeService;
+            if (!mDozing) {
+                mDozing = true;
+                updateDozingState();
+            }
+            mCurrentDozeService.startDozing();
+        }
+
+        private void handleRequestTease(DozeService dozeService) {
+            if (!dozeService.equals(mCurrentDozeService)) return;
+            final long stayAwake = mScrimController.tease();
+            mCurrentDozeService.stayAwake(stayAwake);
+        }
+
+        private void handleDozingStopped(DozeService dozeService) {
+            if (dozeService.equals(mCurrentDozeService)) {
+                mCurrentDozeService = null;
+            }
+            if (mDozing) {
+                mDozing = false;
+                updateDozingState();
+            }
+        }
+
+        private final class H extends Handler {
+            private static final int REQUEST_DOZE = 1;
+            private static final int REQUEST_TEASE = 2;
+            private static final int DOZING_STOPPED = 3;
+
+            @Override
+            public void handleMessage(Message msg) {
+                if (msg.what == REQUEST_DOZE) {
+                    handleRequestDoze((DozeService) msg.obj);
+                } else if (msg.what == REQUEST_TEASE) {
+                    handleRequestTease((DozeService) msg.obj);
+                } else if (msg.what == DOZING_STOPPED) {
+                    handleDozingStopped((DozeService) msg.obj);
+                }
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 1264d75..bf63f7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -21,21 +21,35 @@
 import android.animation.ValueAnimator;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 
+import com.android.systemui.R;
+
 /**
  * Controls both the scrim behind the notifications and in front of the notifications (when a
  * security method gets shown).
  */
 public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
+    private static final String TAG = "ScrimController";
+    private static final boolean DEBUG = false;
 
     private static final float SCRIM_BEHIND_ALPHA = 0.62f;
     private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.5f;
     private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
     private static final long ANIMATION_DURATION = 220;
+    private static final int TAG_KEY_ANIM = R.id.scrim;
+
+    private static final int NUM_TEASES = 3;
+    private static final long TEASE_IN_ANIMATION_DURATION = 500;
+    private static final long TEASE_VISIBLE_DURATION = 3000;
+    private static final long TEASE_OUT_ANIMATION_DURATION = 1000;
+    private static final long TEASE_INVISIBLE_DURATION = 1000;
+    private static final long TEASE_DURATION = TEASE_IN_ANIMATION_DURATION
+            + TEASE_VISIBLE_DURATION + TEASE_OUT_ANIMATION_DURATION + TEASE_INVISIBLE_DURATION;
 
     private final View mScrimBehind;
     private final View mScrimInFront;
@@ -54,6 +68,8 @@
     private long mAnimationDelay;
     private Runnable mOnAnimationFinished;
     private boolean mAnimationStarted;
+    private boolean mDozing;
+    private int mTeasesRemaining;
 
     private final Interpolator mInterpolator = new DecelerateInterpolator();
 
@@ -97,6 +113,29 @@
         scheduleUpdate();
     }
 
+    public void setDozing(boolean dozing) {
+        if (mDozing == dozing) return;
+        mDozing = dozing;
+        if (!mDozing) {
+            cancelTeasing();
+        }
+        scheduleUpdate();
+    }
+
+    /** When dozing, fade screen contents in and out a few times using the front scrim. */
+    public long tease() {
+        if (!mDozing) return 0;
+        mTeasesRemaining = NUM_TEASES;
+        mScrimInFront.post(mTeaseIn);
+        return NUM_TEASES * TEASE_DURATION;
+    }
+
+    private void cancelTeasing() {
+        mTeasesRemaining = 0;
+        mScrimInFront.removeCallbacks(mTeaseIn);
+        mScrimInFront.removeCallbacks(mTeaseOut);
+    }
+
     private void scheduleUpdate() {
         if (mUpdatePending) return;
 
@@ -125,6 +164,8 @@
         } else if (mBouncerShowing) {
             setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
             setScrimBehindColor(0f);
+        } else if (mDozing) {
+            setScrimInFrontColor(1);
         } else {
             setScrimInFrontColor(0f);
             setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD);
@@ -174,6 +215,10 @@
         if (current == targetColor) {
             return;
         }
+        Object runningAnim = scrim.getTag(TAG_KEY_ANIM);
+        if (runningAnim instanceof ValueAnimator) {
+            ((ValueAnimator) runningAnim).cancel();
+        }
         ValueAnimator anim = ValueAnimator.ofInt(current, target);
         anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
@@ -193,9 +238,11 @@
                     mOnAnimationFinished.run();
                     mOnAnimationFinished = null;
                 }
+                scrim.setTag(TAG_KEY_ANIM, null);
             }
         });
         anim.start();
+        scrim.setTag(TAG_KEY_ANIM, anim);
         mAnimationStarted = true;
     }
 
@@ -225,4 +272,51 @@
         mAnimationStarted = false;
         return true;
     }
+
+    private final Runnable mTeaseIn = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG) Log.d(TAG, "Tease in, mDozing=" + mDozing
+                    + " mTeasesRemaining=" + mTeasesRemaining);
+            if (!mDozing || mTeasesRemaining == 0) return;
+            mTeasesRemaining--;
+            mDurationOverride = TEASE_IN_ANIMATION_DURATION;
+            mAnimationDelay = 0;
+            mAnimateChange = true;
+            mOnAnimationFinished = mTeaseInFinished;
+            setScrimColor(mScrimInFront, 0);
+        }
+    };
+
+    private final Runnable mTeaseInFinished = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG) Log.d(TAG, "Tease in finished, mDozing=" + mDozing);
+            if (!mDozing) return;
+            mScrimInFront.postDelayed(mTeaseOut, TEASE_VISIBLE_DURATION);
+        }
+    };
+
+    private final Runnable mTeaseOut = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG) Log.d(TAG, "Tease in finished, mDozing=" + mDozing);
+            if (!mDozing) return;
+            mDurationOverride = TEASE_OUT_ANIMATION_DURATION;
+            mAnimationDelay = 0;
+            mAnimateChange = true;
+            mOnAnimationFinished = mTeaseOutFinished;
+            setScrimColor(mScrimInFront, 1);
+        }
+    };
+
+    private final Runnable mTeaseOutFinished = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG) Log.d(TAG, "Tease out finished, mTeasesRemaining=" + mTeasesRemaining);
+            if (mTeasesRemaining > 0) {
+                mScrimInFront.postDelayed(mTeaseIn, TEASE_INVISIBLE_DURATION);
+            }
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index fcc951e..0582140 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -33,6 +33,7 @@
     private float mOverScrollBottomAmount;
     private int mSpeedBumpIndex = -1;
     private float mScrimAmount;
+    private boolean mDark;
 
     public int getScrollY() {
         return mScrollY;
@@ -62,6 +63,11 @@
         mDimmed = dimmed;
     }
 
+    /** In dark mode, we draw as little as possible, assuming a black background */
+    public void setDark(boolean dark) {
+        mDark = dark;
+    }
+
     /**
      * In dimmed mode, a child can be activated, which happens on the first tap of the double-tap
      * interaction. This child is then scaled normally and its background is fully opaque.
@@ -74,6 +80,10 @@
         return mDimmed;
     }
 
+    public boolean isDark() {
+        return mDark;
+    }
+
     public ActivatableNotificationView getActivatedChild() {
         return mActivatedChild;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index cf56fa57..99d3a01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -29,6 +29,7 @@
     boolean animateHeight;
     boolean animateTopInset;
     boolean animateDimmed;
+    boolean animateDark;
     boolean hasDelays;
 
     public AnimationFilter animateAlpha() {
@@ -71,6 +72,11 @@
         return this;
     }
 
+    public AnimationFilter animateDark() {
+        animateDark = true;
+        return this;
+    }
+
     /**
      * Combines multiple filters into {@code this} filter, using or as the operand .
      *
@@ -92,6 +98,7 @@
         animateHeight |= filter.animateHeight;
         animateTopInset |= filter.animateTopInset;
         animateDimmed |= filter.animateDimmed;
+        animateDark |= filter.animateDark;
         hasDelays |= filter.hasDelays;
     }
 
@@ -103,6 +110,7 @@
         animateHeight = false;
         animateTopInset = false;
         animateDimmed = false;
+        animateDark = false;
         hasDelays = false;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index f6e9aef..4220efe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -128,6 +128,7 @@
     private boolean mNeedsAnimation;
     private boolean mTopPaddingNeedsAnimation;
     private boolean mDimmedNeedsAnimation;
+    private boolean mDarkNeedsAnimation;
     private boolean mActivateNeedsAnimation;
     private boolean mIsExpanded = true;
     private boolean mChildrenUpdateRequested;
@@ -356,14 +357,6 @@
         return getNotGoneChildCount() > 1;
     }
 
-    private boolean isViewExpanded(View view) {
-        if (view != null) {
-            ExpandableView expandView = (ExpandableView) view;
-            return expandView.getActualHeight() > mCollapsedSize;
-        }
-        return false;
-    }
-
     /**
      * Updates the children views according to the stack scroll algorithm. Call this whenever
      * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
@@ -1479,6 +1472,7 @@
         generateTopPaddingEvent();
         generateActivateEvent();
         generateDimmedEvent();
+        generateDarkEvent();
         mNeedsAnimation = false;
     }
 
@@ -1554,6 +1548,14 @@
         mDimmedNeedsAnimation = false;
     }
 
+    private void generateDarkEvent() {
+        if (mDarkNeedsAnimation) {
+            mAnimationEvents.add(
+                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_DARK));
+        }
+        mDarkNeedsAnimation = false;
+    }
+
     private boolean onInterceptTouchEventScroll(MotionEvent ev) {
         if (!isScrollingEnabled()) {
             return false;
@@ -1852,6 +1854,18 @@
     }
 
     /**
+     * See {@link AmbientState#setDark}.
+     */
+    public void setDark(boolean dark, boolean animate) {
+        mAmbientState.setDark(dark);
+        if (animate && mAnimationsEnabled) {
+            mDarkNeedsAnimation = true;
+            mNeedsAnimation =  true;
+        }
+        requestChildrenUpdate();
+    }
+
+    /**
      * A listener that is notified when some child locations might have changed.
      */
     public interface OnChildLocationsChangedListener {
@@ -1940,7 +1954,11 @@
                         .animateHeight()
                         .animateTopInset()
                         .animateY()
-                        .animateZ()
+                        .animateZ(),
+
+                // ANIMATION_TYPE_DARK
+                new AnimationFilter()
+                        .animateDark(),
         };
 
         static int[] LENGTHS = new int[] {
@@ -1971,6 +1989,9 @@
 
                 // ANIMATION_TYPE_CHANGE_POSITION
                 StackStateAnimator.ANIMATION_DURATION_STANDARD,
+
+                // ANIMATION_TYPE_DARK
+                StackStateAnimator.ANIMATION_DURATION_STANDARD,
         };
 
         static final int ANIMATION_TYPE_ADD = 0;
@@ -1982,6 +2003,7 @@
         static final int ANIMATION_TYPE_ACTIVATED_CHILD = 6;
         static final int ANIMATION_TYPE_DIMMED = 7;
         static final int ANIMATION_TYPE_CHANGE_POSITION = 8;
+        static final int ANIMATION_TYPE_DARK = 9;
 
         final long eventStartTime;
         final View changingView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 9a4b798..4956fe8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -233,12 +233,14 @@
     private void updateDimmedActivated(AmbientState ambientState, StackScrollState resultState,
             StackScrollAlgorithmState algorithmState) {
         boolean dimmed = ambientState.isDimmed();
+        boolean dark = ambientState.isDark();
         View activatedChild = ambientState.getActivatedChild();
         int childCount = algorithmState.visibleChildren.size();
         for (int i = 0; i < childCount; i++) {
             View child = algorithmState.visibleChildren.get(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
             childViewState.dimmed = dimmed;
+            childViewState.dark = dark;
             boolean isActivatedChild = activatedChild == child;
             childViewState.scale = !dimmed || isActivatedChild
                     ? 1.0f
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 02f2cd6..d8407d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -148,6 +148,9 @@
                 // apply dimming
                 child.setDimmed(state.dimmed, false /* animate */);
 
+                // apply dark
+                child.setDark(state.dark, false /* animate */);
+
                 // apply scrimming
                 child.setScrimAmount(state.scrimAmount);
 
@@ -224,6 +227,7 @@
         boolean gone;
         float scale;
         boolean dimmed;
+        boolean dark;
 
         /**
          * A value between 0 and 1 indicating how much the view should be scrimmed.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 0006dad..5efbc99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -176,6 +176,9 @@
         // start dimmed animation
         child.setDimmed(viewState.dimmed, mAnimationFilter.animateDimmed);
 
+        // start dark animation
+        child.setDark(viewState.dark, mAnimationFilter.animateDark);
+
         // apply scrimming
         child.setScrimAmount(viewState.scrimAmount);
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 1cab7ea..d514c99b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -34,6 +34,9 @@
 import android.media.AudioSystem;
 import android.media.RingtoneManager;
 import android.media.ToneGenerator;
+import android.media.VolumeProvider;
+import android.media.session.MediaController;
+import android.media.session.MediaController.VolumeInfo;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -224,6 +227,7 @@
     /** Object that contains data for each slider */
     private class StreamControl {
         int streamType;
+        MediaController controller;
         ViewGroup group;
         ImageView icon;
         SeekBar seekbarView;
@@ -405,7 +409,8 @@
         if (streamType == STREAM_MASTER) {
             return mAudioManager.isMasterMute();
         } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
-            return (mAudioManager.getRemoteStreamVolume() <= 0);
+            // TODO do we need to support a distinct mute property for remote?
+            return false;
         } else {
             return mAudioManager.isStreamMute(streamType);
         }
@@ -415,7 +420,14 @@
         if (streamType == STREAM_MASTER) {
             return mAudioManager.getMasterMaxVolume();
         } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
-            return mAudioManager.getRemoteStreamMaxVolume();
+            if (mStreamControls != null) {
+                StreamControl sc = mStreamControls.get(streamType);
+                if (sc != null && sc.controller != null) {
+                    VolumeInfo vi = sc.controller.getVolumeInfo();
+                    return vi.getMaxVolume();
+                }
+            }
+            return -1;
         } else {
             return mAudioManager.getStreamMaxVolume(streamType);
         }
@@ -425,19 +437,32 @@
         if (streamType == STREAM_MASTER) {
             return mAudioManager.getMasterVolume();
         } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
-            return mAudioManager.getRemoteStreamVolume();
+            if (mStreamControls != null) {
+                StreamControl sc = mStreamControls.get(streamType);
+                if (sc != null && sc.controller != null) {
+                    VolumeInfo vi = sc.controller.getVolumeInfo();
+                    return vi.getCurrentVolume();
+                }
+            }
+            return -1;
         } else {
             return mAudioManager.getStreamVolume(streamType);
         }
     }
 
-    private void setStreamVolume(int streamType, int index, int flags) {
-        if (streamType == STREAM_MASTER) {
-            mAudioManager.setMasterVolume(index, flags);
-        } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) {
-            mAudioManager.setRemoteStreamVolume(index);
-        } else {
-            mAudioManager.setStreamVolume(streamType, index, flags);
+    private void setStreamVolume(StreamControl sc, int index, int flags) {
+        if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {
+            if (sc.controller != null) {
+                sc.controller.setVolumeTo(index, flags);
+            } else {
+                Log.wtf(mTag, "Adjusting remote volume without a controller!");
+            }
+        } else if (getStreamVolume(sc.streamType) != index) {
+            if (sc.streamType == STREAM_MASTER) {
+                mAudioManager.setMasterVolume(index, flags);
+            } else {
+                mAudioManager.setStreamVolume(sc.streamType, index, flags);
+            }
         }
     }
 
@@ -549,7 +574,7 @@
         if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {
             // never disable touch interactions for remote playback, the muting is not tied to
             // the state of the phone.
-            sc.seekbarView.setEnabled(true);
+            sc.seekbarView.setEnabled(!fixedVolume);
         } else if (fixedVolume ||
                         (sc.streamType != mAudioManager.getMasterStreamType() && muted) ||
                         (sConfirmSafeVolumeDialog != null)) {
@@ -677,7 +702,7 @@
         obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget();
     }
 
-    public void postRemoteVolumeChanged(int streamType, int flags) {
+    public void postRemoteVolumeChanged(MediaController controller, int flags) {
         if (hasMessages(MSG_REMOTE_VOLUME_CHANGED)) return;
         synchronized (this) {
             if (mStreamControls == null) {
@@ -685,7 +710,7 @@
             }
         }
         removeMessages(MSG_FREE_RESOURCES);
-        obtainMessage(MSG_REMOTE_VOLUME_CHANGED, streamType, flags).sendToTarget();
+        obtainMessage(MSG_REMOTE_VOLUME_CHANGED, flags, 0, controller).sendToTarget();
     }
 
     public void postRemoteSliderVisibility(boolean visible) {
@@ -758,7 +783,7 @@
                 if (mActiveStreamType != streamType) {
                     reorderSliders(streamType);
                 }
-                onShowVolumeChanged(streamType, flags);
+                onShowVolumeChanged(streamType, flags, null);
             }
         }
 
@@ -790,7 +815,7 @@
         onVolumeChanged(streamType, flags);
     }
 
-    protected void onShowVolumeChanged(int streamType, int flags) {
+    protected void onShowVolumeChanged(int streamType, int flags, MediaController controller) {
         int index = getStreamVolume(streamType);
 
         mRingIsSilent = false;
@@ -803,6 +828,7 @@
         // get max volume for progress bar
 
         int max = getStreamMaxVolume(streamType);
+        StreamControl sc = mStreamControls.get(streamType);
 
         switch (streamType) {
 
@@ -865,13 +891,37 @@
             }
 
             case AudioService.STREAM_REMOTE_MUSIC: {
+                if (controller == null && sc != null) {
+                    // If we weren't passed one try using the last one set.
+                    controller = sc.controller;
+                }
+                if (controller == null) {
+                    // We still don't have one, ignore the command.
+                    Log.w(mTag, "sent remote volume change without a controller!");
+                } else {
+                    VolumeInfo vi = controller.getVolumeInfo();
+                    index = vi.getCurrentVolume();
+                    max = vi.getMaxVolume();
+                    if ((vi.getVolumeControl() & VolumeProvider.VOLUME_CONTROL_FIXED) != 0) {
+                        // if the remote volume is fixed add the flag for the UI
+                        flags |= AudioManager.FLAG_FIXED_VOLUME;
+                    }
+                }
                 if (LOGD) { Log.d(mTag, "showing remote volume "+index+" over "+ max); }
                 break;
             }
         }
 
-        StreamControl sc = mStreamControls.get(streamType);
         if (sc != null) {
+            if (streamType == AudioService.STREAM_REMOTE_MUSIC && controller != sc.controller) {
+                if (sc.controller != null) {
+                    sc.controller.removeCallback(mMediaControllerCb);
+                }
+                sc.controller = controller;
+                if (controller != null) {
+                    sc.controller.addCallback(mMediaControllerCb);
+                }
+            }
             if (sc.seekbarView.getMax() != max) {
                 sc.seekbarView.setMax(max);
             }
@@ -949,34 +999,21 @@
         mVibrator.vibrate(VIBRATE_DURATION, AudioManager.STREAM_SYSTEM);
     }
 
-    protected void onRemoteVolumeChanged(int streamType, int flags) {
-        // streamType is the real stream type being affected, but for the UI sliders, we
-        // refer to AudioService.STREAM_REMOTE_MUSIC. We still play the beeps on the real
-        // stream type.
-        if (LOGD) Log.d(mTag, "onRemoteVolumeChanged(stream:"+streamType+", flags: " + flags + ")");
+    protected void onRemoteVolumeChanged(MediaController controller, int flags) {
+        if (LOGD) Log.d(mTag, "onRemoteVolumeChanged(controller:" + controller + ", flags: " + flags
+                    + ")");
 
         if (((flags & AudioManager.FLAG_SHOW_UI) != 0) || isShowing()) {
             synchronized (this) {
                 if (mActiveStreamType != AudioService.STREAM_REMOTE_MUSIC) {
                     reorderSliders(AudioService.STREAM_REMOTE_MUSIC);
                 }
-                onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, flags);
+                onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, flags, controller);
             }
         } else {
             if (LOGD) Log.d(mTag, "not calling onShowVolumeChanged(), no FLAG_SHOW_UI or no UI");
         }
 
-        if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) {
-            removeMessages(MSG_PLAY_SOUND);
-            sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY);
-        }
-
-        if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) {
-            removeMessages(MSG_PLAY_SOUND);
-            removeMessages(MSG_VIBRATE);
-            onStopSounds();
-        }
-
         removeMessages(MSG_FREE_RESOURCES);
         sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY);
         resetTimeout();
@@ -987,10 +1024,24 @@
         if (isShowing()
                 && (mActiveStreamType == AudioService.STREAM_REMOTE_MUSIC)
                 && (mStreamControls != null)) {
-            onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, 0);
+            onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, 0, null);
         }
     }
 
+    /**
+     * Clear the current remote stream controller.
+     */
+    private void clearRemoteStreamController() {
+        if (mStreamControls != null) {
+            StreamControl sc = mStreamControls.get(AudioService.STREAM_REMOTE_MUSIC);
+            if (sc != null) {
+                if (sc.controller != null) {
+                    sc.controller.removeCallback(mMediaControllerCb);
+                    sc.controller = null;
+                }
+            }
+        }
+    }
 
     /**
      * Handler for MSG_SLIDER_VISIBILITY_CHANGED
@@ -1137,6 +1188,7 @@
                 if (isShowing()) {
                     if (mDialog != null) {
                         mDialog.dismiss();
+                        clearRemoteStreamController();
                         mActiveStreamType = -1;
                     }
                 }
@@ -1155,7 +1207,7 @@
             }
 
             case MSG_REMOTE_VOLUME_CHANGED: {
-                onRemoteVolumeChanged(msg.arg1, msg.arg2);
+                onRemoteVolumeChanged((MediaController) msg.obj, msg.arg1);
                 break;
             }
 
@@ -1202,9 +1254,7 @@
             final Object tag = seekBar.getTag();
             if (fromUser && tag instanceof StreamControl) {
                 StreamControl sc = (StreamControl) tag;
-                if (getStreamVolume(sc.streamType) != progress) {
-                    setStreamVolume(sc.streamType, progress, 0);
-                }
+                setStreamVolume(sc, progress, 0);
             }
             resetTimeout();
         }
@@ -1215,19 +1265,6 @@
 
         @Override
         public void onStopTrackingTouch(SeekBar seekBar) {
-            final Object tag = seekBar.getTag();
-            if (tag instanceof StreamControl) {
-                StreamControl sc = (StreamControl) tag;
-                // Because remote volume updates are asynchronous, AudioService
-                // might have received a new remote volume value since the
-                // finger adjusted the slider. So when the progress of the
-                // slider isn't being tracked anymore, adjust the slider to the
-                // last "published" remote volume value, so the UI reflects the
-                // actual volume.
-                if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {
-                    seekBar.setProgress(getStreamVolume(AudioService.STREAM_REMOTE_MUSIC));
-                }
-            }
         }
     };
 
@@ -1257,4 +1294,10 @@
             postZenModeChanged(zen);
         }
     };
+
+    private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {
+        public void onVolumeInfoChanged(VolumeInfo info) {
+            onRemoteVolumeUpdateIfShown();
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 7da90d8..c1f92ff 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -5,7 +5,11 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.media.AudioManager;
+import android.media.IRemoteVolumeController;
 import android.media.IVolumeController;
+import android.media.session.ISessionController;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -42,12 +46,21 @@
 
     private final Handler mHandler = new Handler();
     private AudioManager mAudioManager;
+    private MediaSessionManager mMediaSessionManager;
     private VolumeController mVolumeController;
+    private RemoteVolumeController mRemoteVolumeController;
+
+    private VolumePanel mDialogPanel;
+    private VolumePanel mPanel;
 
     @Override
     public void start() {
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        mVolumeController = new VolumeController(mContext);
+        mMediaSessionManager = (MediaSessionManager) mContext
+                .getSystemService(Context.MEDIA_SESSION_SERVICE);
+        initPanel();
+        mVolumeController = new VolumeController();
+        mRemoteVolumeController = new RemoteVolumeController();
         putComponent(VolumeComponent.class, mVolumeController);
         updateController();
         mContext.getContentResolver().registerContentObserver(SETTING_URI, false, mObserver);
@@ -57,12 +70,32 @@
         if (Settings.Global.getInt(mContext.getContentResolver(), SETTING, DEFAULT) != 0) {
             Log.d(TAG, "Registering volume controller");
             mAudioManager.setVolumeController(mVolumeController);
+            mMediaSessionManager.setRemoteVolumeController(mRemoteVolumeController);
         } else {
             Log.d(TAG, "Unregistering volume controller");
             mAudioManager.setVolumeController(null);
+            mMediaSessionManager.setRemoteVolumeController(null);
         }
     }
 
+    private void initPanel() {
+        mPanel = new VolumePanel(mContext, null, new ZenModeControllerImpl(mContext, mHandler));
+        final int delay = mContext.getResources().getInteger(R.integer.feedback_start_delay);
+        mPanel.setZenModePanelCallback(new ZenModePanel.Callback() {
+            @Override
+            public void onMoreSettings() {
+                mHandler.removeCallbacks(mStartZenSettings);
+                mHandler.postDelayed(mStartZenSettings, delay);
+            }
+
+            @Override
+            public void onInteraction() {
+                mDialogPanel.resetTimeout();
+            }
+        });
+        mDialogPanel = mPanel;
+    }
+
     private final ContentObserver mObserver = new ContentObserver(mHandler) {
         public void onChange(boolean selfChange, Uri uri) {
             if (SETTING_URI.equals(uri)) {
@@ -71,55 +104,18 @@
         }
     };
 
+    private final Runnable mStartZenSettings = new Runnable() {
+        @Override
+        public void run() {
+            mDialogPanel.postDismiss();
+            final Intent intent = ZenModePanel.ZEN_SETTINGS;
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+        }
+    };
+
     /** For now, simply host an unmodified base volume panel in this process. */
     private final class VolumeController extends IVolumeController.Stub implements VolumeComponent {
-        private final VolumePanel mDialogPanel;
-        private VolumePanel mPanel;
-
-        public VolumeController(Context context) {
-            mPanel = new VolumePanel(context, null, new ZenModeControllerImpl(mContext, mHandler));
-            final int delay = context.getResources().getInteger(R.integer.feedback_start_delay);
-            mPanel.setZenModePanelCallback(new ZenModePanel.Callback() {
-                @Override
-                public void onMoreSettings() {
-                    mHandler.removeCallbacks(mStartZenSettings);
-                    mHandler.postDelayed(mStartZenSettings, delay);
-                }
-
-                @Override
-                public void onInteraction() {
-                    mDialogPanel.resetTimeout();
-                }
-            });
-            mDialogPanel = mPanel;
-        }
-
-        private final Runnable mStartZenSettings = new Runnable() {
-            @Override
-            public void run() {
-                mDialogPanel.postDismiss();
-                final Intent intent = ZenModePanel.ZEN_SETTINGS;
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
-            }
-        };
-
-        @Override
-        public void hasNewRemotePlaybackInfo() throws RemoteException {
-            mPanel.postHasNewRemotePlaybackInfo();
-        }
-
-        @Override
-        public void remoteVolumeChanged(int streamType, int flags)
-                throws RemoteException {
-            mPanel.postRemoteVolumeChanged(streamType, flags);
-        }
-
-        @Override
-        public void remoteSliderVisibility(boolean visible)
-                throws RemoteException {
-            mPanel.postRemoteSliderVisibility(visible);
-        }
 
         @Override
         public void displaySafeVolumeWarning(int flags) throws RemoteException {
@@ -163,4 +159,21 @@
             mPanel = panel == null ? mDialogPanel : panel;
         }
     }
+
+    private final class RemoteVolumeController extends IRemoteVolumeController.Stub {
+
+        @Override
+        public void remoteVolumeChanged(ISessionController binder, int flags)
+                throws RemoteException {
+            MediaController controller = MediaController.fromBinder(binder);
+            mPanel.postRemoteVolumeChanged(controller, flags);
+        }
+
+        @Override
+        public void updateRemoteController(ISessionController session) throws RemoteException {
+            mPanel.postRemoteSliderVisibility(session != null);
+            // TODO stash default session in case the slider can be opened other
+            // than by remoteVolumeChanged.
+        }
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 0c16b78..56a8f7c 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -21,6 +21,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.R;
+import com.android.internal.widget.LockPatternUtils;
 
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
@@ -64,6 +65,8 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.WindowManagerInternal;
 import android.view.WindowManagerPolicy.WindowManagerFuncs;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
@@ -94,6 +97,7 @@
     private static final String GLOBAL_ACTION_KEY_SILENT = "silent";
     private static final String GLOBAL_ACTION_KEY_USERS = "users";
     private static final String GLOBAL_ACTION_KEY_SETTINGS = "settings";
+    private static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown";
 
     private final Context mContext;
     private final WindowManagerFuncs mWindowManagerFuncs;
@@ -279,6 +283,8 @@
                 addUsersToMenu(mItems);
             } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
                 mItems.add(getSettingsAction());
+            } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey) && hasTrustAgents()) {
+                mItems.add(getLockdownAction());
             } else {
                 Log.e(TAG, "Invalid global action key " + actionKey);
             }
@@ -317,6 +323,11 @@
         return dialog;
     }
 
+    private boolean hasTrustAgents() {
+        // TODO: Add implementation.
+        return true;
+    }
+
     private final class PowerAction extends SinglePressAction implements LongPressAction {
         private PowerAction() {
             super(com.android.internal.R.drawable.ic_lock_power_off,
@@ -419,6 +430,32 @@
         };
     }
 
+    private Action getLockdownAction() {
+        return new SinglePressAction(com.android.internal.R.drawable.ic_lock_lock,
+                R.string.global_action_lockdown) {
+
+            @Override
+            public void onPress() {
+                new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);
+                try {
+                    WindowManagerGlobal.getWindowManagerService().lockNow(null);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error while trying to lock device.", e);
+                }
+            }
+
+            @Override
+            public boolean showDuringKeyguard() {
+                return true;
+            }
+
+            @Override
+            public boolean showBeforeProvisioning() {
+                return false;
+            }
+        };
+    }
+
     private UserInfo getCurrentUser() {
         try {
             return ActivityManagerNative.getDefault().getCurrentUser();
diff --git a/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java b/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java
index 2cc33b5f..704da33 100644
--- a/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java
+++ b/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java
@@ -193,7 +193,9 @@
             pw.println(prefix + "mSensor=" + mSensor);
             pw.println(prefix + "mRate=" + mRate);
 
-            mSensorEventListener.dumpLocked(pw, prefix);
+            if (mSensorEventListener != null) {
+                mSensorEventListener.dumpLocked(pw, prefix);
+            }
         }
     }
 
diff --git a/rs/java/android/renderscript/ScriptIntrinsic.java b/rs/java/android/renderscript/ScriptIntrinsic.java
index 8719e017..4edce84 100644
--- a/rs/java/android/renderscript/ScriptIntrinsic.java
+++ b/rs/java/android/renderscript/ScriptIntrinsic.java
@@ -27,5 +27,8 @@
 public abstract class ScriptIntrinsic extends Script {
     ScriptIntrinsic(long id, RenderScript rs) {
         super(id, rs);
+        if (id == 0) {
+            throw new RSRuntimeException("Loading of ScriptIntrinsic failed.");
+        }
     }
 }
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index ae39b05..fb3b117 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1051,7 +1051,7 @@
     jint dimsLen = _env->GetArrayLength(dims) * sizeof(int);
     jint *dimsPtr = _env->GetIntArrayElements(dims, NULL);
     rsScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
-                     (const size_t*) dimsPtr, dimsLen);
+                     (const uint32_t*) dimsPtr, dimsLen);
     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
     _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT);
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 00bda06..2f5524e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4713,7 +4713,7 @@
                         LinkProperties lp = mCs.getLinkPropertiesForTypeInternal(
                                 ConnectivityManager.TYPE_MOBILE_HIPRI);
                         boolean linkHasIpv4 = lp.hasIPv4Address();
-                        boolean linkHasIpv6 = lp.hasIPv6Address();
+                        boolean linkHasIpv6 = lp.hasGlobalIPv6Address();
                         log("isMobileOk: linkHasIpv4=" + linkHasIpv4
                                 + " linkHasIpv6=" + linkHasIpv6);
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3bff2ad..9cd5091 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7236,6 +7236,7 @@
         rti.stackId = tr.stack != null ? tr.stack.mStackId : -1;
         rti.userId = tr.userId;
         rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
+        rti.lastActiveTime = tr.lastActiveTime;
         return rti;
     }
 
@@ -13959,6 +13960,8 @@
 
         // Make sure that the user who is receiving this broadcast is started.
         // If not, we will just skip it.
+
+
         if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
             if (callingUid != Process.SYSTEM_UID || (intent.getFlags()
                     & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
@@ -13974,8 +13977,8 @@
          */
         int callingAppId = UserHandle.getAppId(callingUid);
         if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID
-                || callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID
-                || callingUid == 0) {
+            || callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID
+            || callingAppId == Process.NFC_UID || callingUid == 0) {
             // Always okay.
         } else if (callerApp == null || !callerApp.persistent) {
             try {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index a301c4b..57dee2e 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -56,6 +56,7 @@
     private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
     private static final String ATTR_USERID = "user_id";
     private static final String ATTR_TASKTYPE = "task_type";
+    private static final String ATTR_LASTACTIVETIME = "last_active_time";
     private static final String ATTR_LASTDESCRIPTION = "last_description";
     private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
     private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
@@ -136,8 +137,8 @@
     TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
             String _affinity, ComponentName _realActivity, ComponentName _origActivity,
             boolean _rootWasReset, boolean _askedCompatMode, int _taskType, int _userId,
-            String _lastDescription, ArrayList<ActivityRecord> activities, long lastTimeMoved,
-            boolean neverRelinquishIdentity) {
+            String _lastDescription, ArrayList<ActivityRecord> activities, long _lastActiveTime,
+            long lastTimeMoved, boolean neverRelinquishIdentity) {
         mService = service;
         taskId = _taskId;
         intent = _intent;
@@ -152,10 +153,13 @@
         taskType = _taskType;
         mTaskToReturnTo = HOME_ACTIVITY_TYPE;
         userId = _userId;
+        lastActiveTime = _lastActiveTime;
         lastDescription = _lastDescription;
         mActivities = activities;
         mLastTimeMoved = lastTimeMoved;
         mNeverRelinquishIdentity = neverRelinquishIdentity;
+        // Recompute the task description for this task
+        updateTaskDescription();
     }
 
     void touchActiveTime() {
@@ -703,6 +707,7 @@
         out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
         out.attribute(null, ATTR_USERID, String.valueOf(userId));
         out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
+        out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
         out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
         out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
         if (lastDescription != null) {
@@ -753,6 +758,7 @@
         int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
         int userId = 0;
         String lastDescription = null;
+        long lastActiveTime = 0;
         long lastTimeOnTop = 0;
         boolean neverRelinquishIdentity = true;
         int taskId = -1;
@@ -779,6 +785,8 @@
                 userId = Integer.valueOf(attrValue);
             } else if (ATTR_TASKTYPE.equals(attrName)) {
                 taskType = Integer.valueOf(attrValue);
+            } else if (ATTR_LASTACTIVETIME.equals(attrName)) {
+                lastActiveTime = Long.valueOf(attrValue);
             } else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
                 lastDescription = attrValue;
             } else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
@@ -818,8 +826,8 @@
 
         final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
                 affinityIntent, affinity, realActivity, origActivity, rootHasReset,
-                askedCompatMode, taskType, userId, lastDescription, activities, lastTimeOnTop,
-                neverRelinquishIdentity);
+                askedCompatMode, taskType, userId, lastDescription, activities, lastActiveTime,
+                lastTimeOnTop, neverRelinquishIdentity);
 
         for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
             final ActivityRecord r = activities.get(activityNdx);
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 3b55bfc..a6485e9 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -172,11 +172,8 @@
             throw new IllegalArgumentException("You must pass a valid uri and observer");
         }
 
-        final int callingUser = UserHandle.getCallingUserId();
-        if (callingUser != userHandle) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
-                    "no permission to observe other users' provider view");
-        }
+        enforceCrossUserPermission(userHandle,
+                "no permission to observe other users' provider view");
 
         if (userHandle < 0) {
             if (userHandle == UserHandle.USER_CURRENT) {
@@ -346,7 +343,15 @@
      * @param request The request object. Validation of this object is done by its builder.
      */
     public void sync(SyncRequest request) {
-        int userId = UserHandle.getCallingUserId();
+        syncAsUser(request, UserHandle.getCallingUserId());
+    }
+
+    /**
+     * If the user id supplied is different to the calling user, the caller must hold the
+     * INTERACT_ACROSS_USERS_FULL permission.
+     */
+    public void syncAsUser(SyncRequest request, int userId) {
+        enforceCrossUserPermission(userId, "no permission to request sync as user: " + userId);
         int callerUid = Binder.getCallingUid();
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
@@ -399,11 +404,30 @@
      */
     @Override
     public void cancelSync(Account account, String authority, ComponentName cname) {
+        cancelSyncAsUser(account, authority, cname, UserHandle.getCallingUserId());
+    }
+
+    /**
+     * Clear all scheduled sync operations that match the uri and cancel the active sync
+     * if they match the authority and account, if they are present.
+     *
+     * <p> If the user id supplied is different to the calling user, the caller must hold the
+     * INTERACT_ACROSS_USERS_FULL permission.
+     *
+     * @param account filter the pending and active syncs to cancel using this account, or null.
+     * @param authority filter the pending and active syncs to cancel using this authority, or
+     * null.
+     * @param userId the user id for which to cancel sync operations.
+     * @param cname cancel syncs running on this service, or null for provider/account.
+     */
+    @Override
+    public void cancelSyncAsUser(Account account, String authority, ComponentName cname,
+            int userId) {
         if (authority != null && authority.length() == 0) {
             throw new IllegalArgumentException("Authority must be non-empty");
         }
-
-        int userId = UserHandle.getCallingUserId();
+        enforceCrossUserPermission(userId,
+                "no permission to modify the sync settings for user " + userId);
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
         long identityToken = clearCallingIdentity();
@@ -456,9 +480,23 @@
      */
     @Override
     public SyncAdapterType[] getSyncAdapterTypes() {
+        return getSyncAdapterTypesAsUser(UserHandle.getCallingUserId());
+    }
+
+    /**
+     * Get information about the SyncAdapters that are known to the system for a particular user.
+     *
+     * <p> If the user id supplied is different to the calling user, the caller must hold the
+     * INTERACT_ACROSS_USERS_FULL permission.
+     *
+     * @return an array of SyncAdapters that have registered with the system
+     */
+    @Override
+    public SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) {
+        enforceCrossUserPermission(userId,
+                "no permission to read sync settings for user " + userId);
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
-        final int userId = UserHandle.getCallingUserId();
         final long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
@@ -470,10 +508,20 @@
 
     @Override
     public boolean getSyncAutomatically(Account account, String providerName) {
+        return getSyncAutomaticallyAsUser(account, providerName, UserHandle.getCallingUserId());
+    }
+
+    /**
+     * If the user id supplied is different to the calling user, the caller must hold the
+     * INTERACT_ACROSS_USERS_FULL permission.
+     */
+    @Override
+    public boolean getSyncAutomaticallyAsUser(Account account, String providerName, int userId) {
+        enforceCrossUserPermission(userId,
+                "no permission to read the sync settings for user " + userId);
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
 
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
@@ -588,9 +636,18 @@
     }
 
     public int getIsSyncable(Account account, String providerName) {
+        return getIsSyncableAsUser(account, providerName, UserHandle.getCallingUserId());
+    }
+
+    /**
+     * If the user id supplied is different to the calling user, the caller must hold the
+     * INTERACT_ACROSS_USERS_FULL permission.
+     */
+    public int getIsSyncableAsUser(Account account, String providerName, int userId) {
+        enforceCrossUserPermission(userId,
+                "no permission to read the sync settings for user " + userId);
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
-        int userId = UserHandle.getCallingUserId();
 
         long identityToken = clearCallingIdentity();
         try {
@@ -627,10 +684,20 @@
 
     @Override
     public boolean getMasterSyncAutomatically() {
+        return getMasterSyncAutomaticallyAsUser(UserHandle.getCallingUserId());
+    }
+
+    /**
+     * If the user id supplied is different to the calling user, the caller must hold the
+     * INTERACT_ACROSS_USERS_FULL permission.
+     */
+    @Override
+    public boolean getMasterSyncAutomaticallyAsUser(int userId) {
+        enforceCrossUserPermission(userId,
+                "no permission to read the sync settings for user " + userId);
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
 
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
@@ -679,10 +746,19 @@
     }
 
     public List<SyncInfo> getCurrentSyncs() {
+        return getCurrentSyncsAsUser(UserHandle.getCallingUserId());
+    }
+
+    /**
+     * If the user id supplied is different to the calling user, the caller must hold the
+     * INTERACT_ACROSS_USERS_FULL permission.
+     */
+    public List<SyncInfo> getCurrentSyncsAsUser(int userId) {
+        enforceCrossUserPermission(userId,
+                "no permission to read the sync settings for user " + userId);
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
 
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId);
@@ -692,13 +768,24 @@
     }
 
     public SyncStatusInfo getSyncStatus(Account account, String authority, ComponentName cname) {
+        return getSyncStatusAsUser(account, authority, cname, UserHandle.getCallingUserId());
+    }
+
+    /**
+     * If the user id supplied is different to the calling user, the caller must hold the
+     * INTERACT_ACROSS_USERS_FULL permission.
+     */
+    public SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
+            ComponentName cname, int userId) {
         if (TextUtils.isEmpty(authority)) {
             throw new IllegalArgumentException("Authority must not be empty");
         }
+
+        enforceCrossUserPermission(userId,
+                "no permission to read the sync stats for user " + userId);
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
 
-        int userId = UserHandle.getCallingUserId();
         int callerUid = Binder.getCallingUid();
         long identityToken = clearCallingIdentity();
         try {
@@ -772,6 +859,21 @@
     }
 
     /**
+     * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL
+     * permission, if the userHandle is not for the caller.
+     *
+     * @param userHandle the user handle of the user we want to act on behalf of.
+     * @param message the message to log on security exception.
+     */
+    private void enforceCrossUserPermission(int userHandle, String message) {
+        final int callingUser = UserHandle.getCallingUserId();
+        if (callingUser != userHandle) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
+        }
+    }
+
+    /**
      * Hide this class since it is not part of api,
      * but current unittest framework requires it to be public
      * @hide
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 8968da3..ed4ccfc 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -103,6 +103,9 @@
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+            if (Build.IS_DEBUGGABLE) {
+                SystemProperties.addChangeCallback(mSystemPropertiesChanged);
+            }
             mContext.registerReceiver(new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
@@ -127,6 +130,7 @@
         pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze);
         pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing);
         pw.println("mCurrentDreamDozeHardware=" + mCurrentDreamDozeHardware);
+        pw.println("getDozeComponent()=" + getDozeComponent());
         pw.println();
 
         DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
@@ -653,4 +657,18 @@
             }
         }
     }
+
+    private final Runnable mSystemPropertiesChanged = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG) Slog.d(TAG, "System properties changed");
+            synchronized(mLock) {
+                if (mCurrentDreamName != null && mCurrentDreamCanDoze
+                        && !mCurrentDreamName.equals(getDozeComponent())) {
+                    // may have updated the doze component, wake up
+                    stopDreamLocked();
+                }
+            }
+        }
+    };
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 2b53895..0333dbf 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -20,6 +20,7 @@
 import android.hardware.hdmi.HdmiCecDeviceInfo;
 import android.hardware.hdmi.HdmiCecMessage;
 import android.hardware.hdmi.IHdmiControlCallback;
+import android.media.AudioSystem;
 import android.os.RemoteException;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -47,7 +48,6 @@
     @GuardedBy("mLock")
     private boolean mSystemAudioMode;
 
-
     // Copy of mDeviceInfos to guarantee thread-safety.
     @GuardedBy("mLock")
     private List<HdmiCecDeviceInfo> mSafeAllDeviceInfos = Collections.emptyList();
@@ -312,15 +312,21 @@
             boolean oldStatus = mArcStatusEnabled;
             // 1. Enable/disable ARC circuit.
             mService.setAudioReturnChannel(enabled);
-
-            // TODO: notify arc mode change to AudioManager.
-
-            // 2. Update arc status;
+            // 2. Notify arc status to audio service.
+            notifyArcStatusToAudioService(enabled);
+            // 3. Update arc status;
             mArcStatusEnabled = enabled;
             return oldStatus;
         }
     }
 
+    private void notifyArcStatusToAudioService(boolean enabled) {
+        // Note that we don't set any name to ARC.
+        mService.getAudioManager().setWiredDeviceConnectionState(
+                AudioSystem.DEVICE_OUT_HDMI_ARC,
+                enabled ? 1 : 0, "");
+    }
+
     /**
      * Returns whether ARC is enabled or not.
      */
@@ -613,7 +619,6 @@
     @ServiceThreadOnly
     void onHotplug(int portNo, boolean connected) {
         assertRunOnServiceThread();
-        // TODO: delegate onHotplug event to each local device.
 
         // Tv device will have permanent HotplugDetectionAction.
         List<HotplugDetectionAction> hotplugActions = getActions(HotplugDetectionAction.class);
@@ -623,10 +628,4 @@
             hotplugActions.get(0).pollAllDevicesNow();
         }
     }
-
-    boolean canChangeSystemAudio() {
-        // TODO: implement this.
-        // return true if no system audio control sequence is running.
-        return false;
-    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 1a18c10..53cb81d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -28,6 +28,7 @@
 import android.hardware.hdmi.IHdmiDeviceEventListener;
 import android.hardware.hdmi.IHdmiHotplugEventListener;
 import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
+import android.media.AudioManager;
 import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -870,4 +871,8 @@
     private HdmiCecLocalDevicePlayback playback() {
         return (HdmiCecLocalDevicePlayback) mCecController.getLocalDevice(HdmiCec.DEVICE_PLAYBACK);
     }
+
+    AudioManager getAudioManager() {
+        return (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
index 845eaa9..6f4164b 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
@@ -115,6 +115,7 @@
     }
 
     private boolean canChangeSystemAudio() {
-        return tv().canChangeSystemAudio();
+        return !(tv().hasAction(SystemAudioActionFromTv.class)
+               || tv().hasAction(SystemAudioActionFromAvr.class));
     }
 }
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 1264741..6f1eb8f 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -16,11 +16,9 @@
 
 package com.android.server.media;
 
-import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.media.routeprovider.RouteRequest;
 import android.media.session.ISessionController;
 import android.media.session.ISessionControllerCallback;
@@ -49,7 +47,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -87,6 +84,12 @@
      */
     private static final int ACTIVE_BUFFER = 30000;
 
+    /**
+     * The amount of time we'll send an assumed volume after the last volume
+     * command before reverting to the last reported volume.
+     */
+    private static final int OPTIMISTIC_VOLUME_TIMEOUT = 1000;
+
     private final MessageHandler mHandler;
 
     private final int mOwnerPid;
@@ -122,11 +125,12 @@
 
     // Volume handling fields
     private AudioManager mAudioManager;
-    private int mVolumeType = MediaSession.VOLUME_TYPE_LOCAL;
+    private int mVolumeType = MediaSession.PLAYBACK_TYPE_LOCAL;
     private int mAudioStream = AudioManager.STREAM_MUSIC;
     private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
     private int mMaxVolume = 0;
     private int mCurrentVolume = 0;
+    private int mOptimisticVolume = -1;
     // End volume handling fields
 
     private boolean mIsActive = false;
@@ -276,7 +280,7 @@
      * @param delta The amount to adjust the volume by.
      */
     public void adjustVolumeBy(int delta, int flags) {
-        if (mVolumeType == MediaSession.VOLUME_TYPE_LOCAL) {
+        if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
             if (delta == 0) {
                 mAudioManager.adjustStreamVolume(mAudioStream, delta, flags);
             } else {
@@ -298,18 +302,46 @@
                 return;
             }
             mSessionCb.adjustVolumeBy(delta);
+
+            int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
+            mOptimisticVolume = volumeBefore + delta;
+            mOptimisticVolume = Math.max(0, Math.min(mOptimisticVolume, mMaxVolume));
+            mHandler.removeCallbacks(mClearOptimisticVolumeRunnable);
+            mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT);
+            if (volumeBefore != mOptimisticVolume) {
+                pushVolumeUpdate();
+            }
+
+            if (DEBUG) {
+                Log.d(TAG, "Adjusted optimistic volume to " + mOptimisticVolume + " max is "
+                        + mMaxVolume);
+            }
         }
     }
 
     public void setVolumeTo(int value, int flags) {
-        if (mVolumeType == MediaSession.VOLUME_TYPE_LOCAL) {
+        if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
             mAudioManager.setStreamVolume(mAudioStream, value, flags);
         } else {
             if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) {
                 // Nothing to do. The volume can't be set directly.
                 return;
             }
+            value = Math.max(0, Math.min(value, mMaxVolume));
             mSessionCb.setVolumeTo(value);
+
+            int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
+            mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume));
+            mHandler.removeCallbacks(mClearOptimisticVolumeRunnable);
+            mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT);
+            if (volumeBefore != mOptimisticVolume) {
+                pushVolumeUpdate();
+            }
+
+            if (DEBUG) {
+                Log.d(TAG, "Set optimistic volume to " + mOptimisticVolume + " max is "
+                        + mMaxVolume);
+            }
         }
     }
 
@@ -427,6 +459,16 @@
     }
 
     /**
+     * Get the volume we'd like it to be set to. This is only valid for a short
+     * while after a call to adjust or set volume.
+     *
+     * @return The current optimistic volume or -1.
+     */
+    public int getOptimisticVolume() {
+        return mOptimisticVolume;
+    }
+
+    /**
      * @return True if this session is currently connected to a route.
      */
     public boolean isConnected() {
@@ -542,8 +584,7 @@
                     cb.onPlaybackStateChanged(mPlaybackState);
                 } catch (DeadObjectException e) {
                     mControllerCallbacks.remove(i);
-                    Log.w(TAG, "Removed dead callback in pushPlaybackStateUpdate. size="
-                            + mControllerCallbacks.size() + " cb=" + cb, e);
+                    Log.w(TAG, "Removed dead callback in pushPlaybackStateUpdate.", e);
                 } catch (RemoteException e) {
                     Log.w(TAG, "unexpected exception in pushPlaybackStateUpdate.", e);
                 }
@@ -561,10 +602,29 @@
                 try {
                     cb.onMetadataChanged(mMetadata);
                 } catch (DeadObjectException e) {
-                    Log.w(TAG, "Removing dead callback in pushMetadataUpdate. " + cb, e);
+                    Log.w(TAG, "Removing dead callback in pushMetadataUpdate. ", e);
                     mControllerCallbacks.remove(i);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "unexpected exception in pushMetadataUpdate. " + cb, e);
+                    Log.w(TAG, "unexpected exception in pushMetadataUpdate. ", e);
+                }
+            }
+        }
+    }
+
+    private void pushVolumeUpdate() {
+        synchronized (mLock) {
+            if (mDestroyed) {
+                return;
+            }
+            ParcelableVolumeInfo info = mController.getVolumeAttributes();
+            for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
+                ISessionControllerCallback cb = mControllerCallbacks.get(i);
+                try {
+                    cb.onVolumeInfoChanged(info);
+                } catch (DeadObjectException e) {
+                    Log.w(TAG, "Removing dead callback in pushVolumeUpdate. ", e);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Unexpected exception in pushVolumeUpdate. ", e);
                 }
             }
         }
@@ -680,6 +740,17 @@
         }
     };
 
+    private final Runnable mClearOptimisticVolumeRunnable = new Runnable() {
+        @Override
+        public void run() {
+            boolean needUpdate = (mOptimisticVolume != mCurrentVolume);
+            mOptimisticVolume = -1;
+            if (needUpdate) {
+                pushVolumeUpdate();
+            }
+        }
+    };
+
     private final class SessionStub extends ISession.Stub {
         @Override
         public void destroy() {
@@ -785,12 +856,14 @@
         @Override
         public void setCurrentVolume(int volume) {
             mCurrentVolume = volume;
+            mHandler.post(MessageHandler.MSG_UPDATE_VOLUME);
         }
 
         @Override
         public void configureVolumeHandling(int type, int arg1, int arg2) throws RemoteException {
+            boolean typeChanged = type != mVolumeType;
             switch(type) {
-                case MediaSession.VOLUME_TYPE_LOCAL:
+                case MediaSession.PLAYBACK_TYPE_LOCAL:
                     mVolumeType = type;
                     int audioStream = arg1;
                     if (isValidStream(audioStream)) {
@@ -800,7 +873,7 @@
                         mAudioStream = AudioManager.STREAM_MUSIC;
                     }
                     break;
-                case MediaSession.VOLUME_TYPE_REMOTE:
+                case MediaSession.PLAYBACK_TYPE_REMOTE:
                     mVolumeType = type;
                     mVolumeControlType = arg1;
                     mMaxVolume = arg2;
@@ -809,6 +882,9 @@
                     throw new IllegalArgumentException("Volume handling type " + type
                             + " not recognized.");
             }
+            if (typeChanged) {
+                mService.onSessionPlaybackTypeChanged(MediaSessionRecord.this);
+            }
         }
 
         private boolean isValidStream(int stream) {
@@ -1027,10 +1103,11 @@
                 int type;
                 int max;
                 int current;
-                if (mVolumeType == MediaSession.VOLUME_TYPE_REMOTE) {
+                if (mVolumeType == MediaSession.PLAYBACK_TYPE_REMOTE) {
                     type = mVolumeControlType;
                     max = mMaxVolume;
-                    current = mCurrentVolume;
+                    current = mOptimisticVolume != -1 ? mOptimisticVolume
+                            : mCurrentVolume;
                 } else {
                     type = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
                     max = mAudioManager.getStreamMaxVolume(mAudioStream);
@@ -1130,6 +1207,7 @@
         private static final int MSG_UPDATE_ROUTE_FILTERS = 5;
         private static final int MSG_SEND_COMMAND = 6;
         private static final int MSG_UPDATE_SESSION_STATE = 7;
+        private static final int MSG_UPDATE_VOLUME = 8;
 
         public MessageHandler(Looper looper) {
             super(looper);
@@ -1157,6 +1235,9 @@
                 case MSG_UPDATE_SESSION_STATE:
                     // TODO add session state
                     break;
+                case MSG_UPDATE_VOLUME:
+                    pushVolumeUpdate();
+                    break;
             }
         }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index c0b7d68..fe68a86 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -27,8 +27,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.media.AudioManager;
 import android.media.IAudioService;
+import android.media.IRemoteVolumeController;
 import android.media.routeprovider.RouteRequest;
 import android.media.session.IActiveSessionsListener;
 import android.media.session.ISession;
@@ -98,8 +98,9 @@
     // session so we drop late callbacks properly.
     private int mShowRoutesRequestId = 0;
 
-    // TODO refactor to have per user state for providers. See
-    // MediaRouterService for an example
+    // Used to notify system UI when remote volume was changed. TODO find a
+    // better way to handle this.
+    private IRemoteVolumeController mRvc;
 
     public MediaSessionService(Context context) {
         super(context);
@@ -225,6 +226,16 @@
         }
     }
 
+    public void onSessionPlaybackTypeChanged(MediaSessionRecord record) {
+        synchronized (mLock) {
+            if (!mAllSessions.contains(record)) {
+                Log.d(TAG, "Unknown session changed playback type. Ignoring.");
+                return;
+            }
+            pushRemoteVolumeUpdateLocked(record.getUserId());
+        }
+    }
+
     @Override
     public void onStartUser(int userHandle) {
         updateUser();
@@ -367,6 +378,13 @@
         }
     }
 
+    private void enforceStatusBarPermission(String action, int pid, int uid) {
+        if (getContext().checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
+                pid, uid) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Only system ui may " + action);
+        }
+    }
+
     /**
      * This checks if the component is an enabled notification listener for the
      * specified user. Enabled components may only operate on behalf of the user
@@ -497,6 +515,7 @@
             for (int i = 0; i < size; i++) {
                 tokens.add(new MediaSessionToken(records.get(i).getControllerBinder()));
             }
+            pushRemoteVolumeUpdateLocked(userId);
             for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
                 SessionsListenerRecord record = mSessionsListeners.get(i);
                 if (record.mUserId == UserHandle.USER_ALL || record.mUserId == userId) {
@@ -512,6 +531,17 @@
         }
     }
 
+    private void pushRemoteVolumeUpdateLocked(int userId) {
+        if (mRvc != null) {
+            try {
+                MediaSessionRecord record = mPriorityStack.getDefaultRemoteSession(userId);
+                mRvc.updateRemoteController(record == null ? null : record.getControllerBinder());
+            } catch (RemoteException e) {
+                Log.wtf(TAG, "Error sending default remote volume to sys ui.", e);
+            }
+        }
+    }
+
     private void persistMediaButtonReceiverLocked(MediaSessionRecord record) {
         ComponentName receiver = record.getMediaButtonReceiver();
         if (receiver != null) {
@@ -844,6 +874,19 @@
         }
 
         @Override
+        public void setRemoteVolumeController(IRemoteVolumeController rvc) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                enforceStatusBarPermission("listen for volume changes", pid, uid);
+                mRvc = rvc;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
             if (getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -929,6 +972,13 @@
                 }
             } else {
                 session.adjustVolumeBy(delta, flags);
+                if (mRvc != null) {
+                    try {
+                        mRvc.remoteVolumeChanged(session.getControllerBinder(), flags);
+                    } catch (Exception e) {
+                        Log.wtf(TAG, "Error sending volume change to system UI.", e);
+                    }
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 144ccfa..e26a2eb 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -203,6 +203,19 @@
         return null;
     }
 
+    public MediaSessionRecord getDefaultRemoteSession(int userId) {
+        ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId);
+
+        int size = records.size();
+        for (int i = 0; i < size; i++) {
+            MediaSessionRecord record = records.get(i);
+            if (record.getPlaybackType() == MediaSession.PLAYBACK_TYPE_REMOTE) {
+                return record;
+            }
+        }
+        return null;
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         ArrayList<MediaSessionRecord> sortedSessions = getPriorityListLocked(false, 0,
                 UserHandle.USER_ALL);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 32546df..1aec569 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -88,6 +88,7 @@
     private static final int MSG_UNREGISTER_LISTENER = 2;
     private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
     private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
+    private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
 
     private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
     private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
@@ -314,6 +315,17 @@
         }
     }
 
+
+    private void requireCredentialEntry(int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            mUserHasAuthenticatedSinceBoot.clear();
+            updateTrustAll();
+        } else {
+            mUserHasAuthenticatedSinceBoot.put(userId, false);
+            updateTrust(userId);
+        }
+    }
+
     // Listeners
 
     private void addListener(ITrustListener listener) {
@@ -367,6 +379,17 @@
         }
 
         @Override
+        public void reportRequireCredentialEntry(int userId) throws RemoteException {
+            enforceReportPermission();
+            if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
+                mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
+            } else {
+                throw new IllegalArgumentException(
+                        "userId must be an explicit user id or USER_ALL");
+            }
+        }
+
+        @Override
         public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
             enforceListenerPermission();
             mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
@@ -379,8 +402,8 @@
         }
 
         private void enforceReportPermission() {
-            mContext.enforceCallingPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE,
-                    "reporting trust events");
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
         }
 
         private void enforceListenerPermission() {
@@ -460,6 +483,9 @@
                 case MSG_ENABLED_AGENTS_CHANGED:
                     refreshAgentList();
                     break;
+                case MSG_REQUIRE_CREDENTIAL_ENTRY:
+                    requireCredentialEntry(msg.arg1);
+                    break;
             }
         }
     };
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 6798f3f..61fdaccb 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -214,6 +214,9 @@
                 if (DEBUG) Slog.d(TAG, "add " + info.getId());
                 userState.inputMap.put(info.getId(), info);
                 userState.packageList.add(si.packageName);
+
+                // Reconnect the service if existing input is updated.
+                updateServiceConnectionLocked(info.getId(), userId);
             } catch (IOException | XmlPullParserException e) {
                 Slog.e(TAG, "Can't load TV input " + si.name, e);
             }
@@ -353,6 +356,9 @@
 
             Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(
                     userState.inputMap.get(inputId).getComponent());
+            // Binding service may fail if the service is updating.
+            // In that case, the connection will be revived in buildTvInputListLocked called by
+            // onSomePackagesChanged.
             serviceState.mBound = mContext.bindServiceAsUser(
                     i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId));
         } else if (serviceState.mService != null && isStateEmpty) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9c38bbc..893a891 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2255,9 +2255,12 @@
         try {
             LockPatternUtils utils = new LockPatternUtils(mContext);
             utils.saveLockPassword(password, quality, false, userHandle);
+            boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
+            if (requireEntry) {
+                utils.requireCredentialEntry(UserHandle.USER_ALL);
+            }
             synchronized (this) {
-                int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
-                        != 0 ? callingUid : -1;
+                int newOwner = requireEntry ? callingUid : -1;
                 if (policy.mPasswordOwner != newOwner) {
                     policy.mPasswordOwner = newOwner;
                     saveSettingsLocked(userHandle);
@@ -2370,6 +2373,7 @@
             getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
                     PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
             // Ensure the device is locked
+            new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);
             getWindowManager().lockNow(null);
         } catch (RemoteException e) {
         } finally {
diff --git a/telecomm/java/android/telecomm/CallServiceAdapter.java b/telecomm/java/android/telecomm/CallServiceAdapter.java
index 30084d0..31e37c4 100644
--- a/telecomm/java/android/telecomm/CallServiceAdapter.java
+++ b/telecomm/java/android/telecomm/CallServiceAdapter.java
@@ -135,6 +135,20 @@
     }
 
     /**
+     * Tells Telecomm to cancel the call.
+     *
+     * @param callId The ID of the outgoing call.
+     */
+    public void cancelOutgoingCall(String callId) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.cancelOutgoingCall(callId);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /**
      * Sets a call's state to active (e.g., an ongoing call where two parties can actively
      * communicate).
      *
diff --git a/telecomm/java/android/telecomm/CallVideoProvider.java b/telecomm/java/android/telecomm/CallVideoProvider.java
new file mode 100644
index 0000000..6126fca
--- /dev/null
+++ b/telecomm/java/android/telecomm/CallVideoProvider.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecomm;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+
+import com.android.internal.telecomm.ICallVideoProvider;
+
+/** @hide */
+public abstract class CallVideoProvider {
+    private static final int MSG_SET_CAMERA = 1;
+
+    /**
+     * Default handler used to consolidate binder method calls onto a single thread.
+     */
+    private final class CallVideoProviderHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SET_CAMERA:
+                    setCamera((String) msg.obj);
+                default:
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Default ICallVideoProvider implementation.
+     */
+    private final class CallVideoProviderBinder extends ICallVideoProvider.Stub {
+        public void setCamera(String cameraId) {
+            mMessageHandler.obtainMessage(MSG_SET_CAMERA, cameraId).sendToTarget();
+        }
+    }
+
+    private final CallVideoProviderHandler mMessageHandler = new CallVideoProviderHandler();
+    private final CallVideoProviderBinder mBinder;
+
+    protected CallVideoProvider() {
+        mBinder = new CallVideoProviderBinder();
+    }
+
+    /**
+     * Sets the camera to be used for video recording in a video call.
+     *
+     * @param cameraId The id of the camera.
+     */
+    public abstract void setCamera(String cameraId);
+}
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 4b69a3c..23b99fa 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -52,6 +52,35 @@
     private Uri mSubscriptionLookupHandle;
     private boolean mAreSubscriptionsInitialized = false;
 
+    /**
+     * A callback for providing the resuilt of creating a connection.
+     */
+    public interface OutgoingCallResponse<CONNECTION> {
+        /**
+         * Tells Telecomm that an attempt to place the specified outgoing call succeeded.
+         *
+         * @param request The original request.
+         * @param connection The connection.
+         */
+        void onSuccess(ConnectionRequest request, CONNECTION connection);
+
+        /**
+         * Tells Telecomm that an attempt to place the specified outgoing call failed.
+         *
+         * @param request The original request.
+         * @param code An integer code indicating the reason for failure.
+         * @param msg A message explaining the reason for failure.
+         */
+        void onFailure(ConnectionRequest request, int code, String msg);
+
+        /**
+         * Tells Telecomm to cancel the call.
+         *
+         * @param request The original request.
+         */
+        void onCancel(ConnectionRequest request);
+    }
+
     private final Connection.Listener mConnectionListener = new Connection.Listener() {
         @Override
         public void onStateChanged(Connection c, int state) {
@@ -136,30 +165,24 @@
                         callInfo.getId(),
                         callInfo.getHandle(),
                         callInfo.getExtras()),
-                new Response<ConnectionRequest, Connection>() {
+                new OutgoingCallResponse<Connection>() {
                     @Override
-                    public void onResult(ConnectionRequest request, Connection... result) {
-                        if (result != null && result.length != 1) {
-                            Log.d(this, "adapter handleFailedOutgoingCall %s", callInfo);
-                            getAdapter().handleFailedOutgoingCall(
-                                    request,
-                                    DisconnectCause.ERROR_UNSPECIFIED,
-                                    "Created " + result.length + " Connections, expected 1");
-                            for (Connection c : result) {
-                                c.abort();
-                            }
-                        } else {
-                            Log.d(this, "adapter handleSuccessfulOutgoingCall %s",
-                                    callInfo.getId());
-                            getAdapter().handleSuccessfulOutgoingCall(callInfo.getId());
-                            addConnection(callInfo.getId(), result[0]);
-                        }
+                    public void onSuccess(ConnectionRequest request, Connection connection) {
+                        Log.d(this, "adapter handleSuccessfulOutgoingCall %s",
+                                callInfo.getId());
+                        getAdapter().handleSuccessfulOutgoingCall(callInfo.getId());
+                        addConnection(callInfo.getId(), connection);
                     }
 
                     @Override
-                    public void onError(ConnectionRequest request, int code, String msg) {
+                    public void onFailure(ConnectionRequest request, int code, String msg) {
                         getAdapter().handleFailedOutgoingCall(request, code, msg);
                     }
+
+                    @Override
+                    public void onCancel(ConnectionRequest request) {
+                        getAdapter().cancelOutgoingCall(callInfo.getId());
+                    }
                 }
         );
     }
@@ -389,7 +412,7 @@
 
     public void createRemoteOutgoingConnection(
             ConnectionRequest request,
-            SimpleResponse<ConnectionRequest, RemoteConnection> response) {
+            OutgoingCallResponse<RemoteConnection> response) {
         mRemoteConnectionManager.createOutgoingConnection(request, response);
     }
 
@@ -408,7 +431,7 @@
      */
     public void onCreateConnections(
             ConnectionRequest request,
-            Response<ConnectionRequest, Connection> callback) {}
+            OutgoingCallResponse<Connection> callback) {}
 
     /**
      * Returns a new or existing conference connection when the the user elects to convert the
diff --git a/telecomm/java/android/telecomm/RemoteConnectionManager.java b/telecomm/java/android/telecomm/RemoteConnectionManager.java
index 4201f23..465fae0 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionManager.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionManager.java
@@ -57,7 +57,7 @@
 
     public void createOutgoingConnection(
             ConnectionRequest request,
-            final SimpleResponse<ConnectionRequest, RemoteConnection> response) {
+            final ConnectionService.OutgoingCallResponse response) {
         Subscription subscription = request.getSubscription();
         if (subscription == null) {
             throw new IllegalArgumentException("subscription must be specified.");
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 86a43cb..7658a76d 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -43,7 +43,7 @@
 
     private String mConnectionId;
     private ConnectionRequest mPendingRequest;
-    private SimpleResponse<ConnectionRequest, RemoteConnection> mPendingResponse;
+    private ConnectionService.OutgoingCallResponse<RemoteConnection> mPendingOutgoingCallResponse;
     // Remote connection services only support a single connection.
     private RemoteConnection mConnection;
 
@@ -60,7 +60,7 @@
         public void handleSuccessfulOutgoingCall(String connectionId) {
             if (isPendingConnection(connectionId)) {
                 mConnection = new RemoteConnection(mCallService, connectionId);
-                mPendingResponse.onResult(mPendingRequest, mConnection);
+                mPendingOutgoingCallResponse.onSuccess(mPendingRequest, mConnection);
                 clearPendingInformation();
             }
         }
@@ -72,7 +72,17 @@
             if (isPendingConnection(request.getCallId())) {
                 // Use mPendingRequest instead of request so that we use the same object that was
                 // passed in to us.
-                mPendingResponse.onError(request);
+                mPendingOutgoingCallResponse.onFailure(mPendingRequest, errorCode, errorMessage);
+                mConnectionId = null;
+                clearPendingInformation();
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void cancelOutgoingCall(String connectionId) {
+            if (isPendingConnection(connectionId)) {
+                mPendingOutgoingCallResponse.onCancel(mPendingRequest);
                 mConnectionId = null;
                 clearPendingInformation();
             }
@@ -208,7 +218,7 @@
      */
     public void createOutgoingConnection(
             ConnectionRequest request,
-            SimpleResponse<ConnectionRequest, RemoteConnection> response) {
+            ConnectionService.OutgoingCallResponse<RemoteConnection> response) {
 
         if (mConnectionId == null) {
             String id = UUID.randomUUID().toString();
@@ -216,13 +226,13 @@
             try {
                 mCallService.call(callInfo);
                 mConnectionId = id;
-                mPendingResponse = response;
+                mPendingOutgoingCallResponse = response;
                 mPendingRequest = request;
             } catch (RemoteException e) {
-                response.onError(request);
+                response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, e.toString());
             }
         } else {
-            response.onError(request);
+            response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, null);
         }
     }
 
@@ -254,7 +264,7 @@
     }
 
     private boolean isPendingConnection(String id) {
-        return TextUtils.equals(mConnectionId, id) && mPendingResponse != null;
+        return TextUtils.equals(mConnectionId, id) && mPendingOutgoingCallResponse != null;
     }
 
     private boolean isCurrentConnection(String id) {
@@ -263,7 +273,7 @@
 
     private void clearPendingInformation() {
         mPendingRequest = null;
-        mPendingResponse = null;
+        mPendingOutgoingCallResponse = null;
     }
 
     private void destroyConnection() {
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index a97e7e4..a0abc28 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -16,7 +16,12 @@
 
 package android.telecomm;
 
+import android.annotation.SystemApi;
+import android.content.ComponentName;
 import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
 
 import com.android.internal.telecomm.ITelecommService;
 
@@ -25,11 +30,14 @@
  */
 public class TelecommManager {
     private static final String TAG = "TelecommManager";
+    private static final String TELECOMM_SERVICE_NAME = "telecomm";
 
     private final Context mContext;
     private final ITelecommService mService;
 
-    /** @hide */
+    /**
+     * @hide
+     */
     public TelecommManager(Context context, ITelecommService service) {
         Context appContext = context.getApplicationContext();
         if (appContext != null) {
@@ -41,8 +49,27 @@
         mService = service;
     }
 
-    /** {@hide} */
+    /**
+     * @hide
+     */
     public static TelecommManager from(Context context) {
         return (TelecommManager) context.getSystemService(Context.TELECOMM_SERVICE);
     }
+
+    /**
+     * @hide
+     */
+    @SystemApi
+    public ComponentName getDefaultPhoneApp() {
+        try {
+            return getTelecommService().getDefaultPhoneApp();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException attempting to get the default phone app.", e);
+        }
+        return null;
+    }
+
+    private ITelecommService getTelecommService() {
+        return ITelecommService.Stub.asInterface(ServiceManager.getService(TELECOMM_SERVICE_NAME));
+    }
 }
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
index 87c8859..373fb16 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
@@ -35,6 +35,8 @@
 
     void handleFailedOutgoingCall(in ConnectionRequest request, int errorCode, String errorMessage);
 
+    void cancelOutgoingCall(String callId);
+
     void setActive(String callId);
 
     void setRinging(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/ICallVideoProvider.aidl b/telecomm/java/com/android/internal/telecomm/ICallVideoProvider.aidl
new file mode 100644
index 0000000..c116dcb
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecomm/ICallVideoProvider.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telecomm;
+
+/**
+ * Internal remote interface for a call video provider.
+ * @see android.telecomm.CallVideoProvider
+ * @hide
+ */
+oneway interface ICallVideoProvider {
+    void setCamera(String cameraId);
+}
\ No newline at end of file
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index c758c6d..2ae5768 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.telecomm;
 
+import android.content.ComponentName;
 import android.telecomm.Subscription;
 
 /**
@@ -55,4 +56,9 @@
      * Sets a given Subscription as the system default.
      */
     void setSystemDefault(in Subscription subscription);
+
+    /**
+     * Returns the component name of the default phone application.
+     */
+    ComponentName getDefaultPhoneApp();
 }
diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.aidl b/telephony/java/com/android/ims/ImsCallForwardInfo.aidl
new file mode 100644
index 0000000..a7c3f9a5
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsCallForwardInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.android.ims;
+
+parcelable ImsCallForwardInfo;
diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.java b/telephony/java/com/android/ims/ImsCallForwardInfo.java
new file mode 100644
index 0000000..3f8fd19
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsCallForwardInfo.java
@@ -0,0 +1,88 @@
+/*
+ * 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 com.android.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Provides the call forward information for the supplementary service configuration.
+ *
+ * @hide
+ */
+public class ImsCallForwardInfo implements Parcelable {
+    // Refer to ImsUtInterface#CDIV_CF_XXX
+    public int mCondition;
+    // 0: disabled, 1: enabled
+    public int mStatus;
+    // 0x91: International, 0x81: Unknown
+    public int mToA;
+    // Number (it will not include the "sip" or "tel" URI scheme)
+    public String mNumber;
+    // No reply timer for CF
+    public int mTimeSeconds;
+
+    public ImsCallForwardInfo() {
+    }
+
+    public ImsCallForwardInfo(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mCondition);
+        out.writeInt(mStatus);
+        out.writeInt(mToA);
+        out.writeString(mNumber);
+        out.writeInt(mTimeSeconds);
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + ", Condition: " + mCondition
+            + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled")
+            + ", ToA: " + mToA + ", Number=" + mNumber
+            + ", Time (seconds): " + mTimeSeconds;
+    }
+
+    private void readFromParcel(Parcel in) {
+        mCondition = in.readInt();
+        mStatus = in.readInt();
+        mToA = in.readInt();
+        mNumber = in.readString();
+        mTimeSeconds = in.readInt();
+    }
+
+    public static final Creator<ImsCallForwardInfo> CREATOR =
+            new Creator<ImsCallForwardInfo>() {
+        @Override
+        public ImsCallForwardInfo createFromParcel(Parcel in) {
+            return new ImsCallForwardInfo(in);
+        }
+
+        @Override
+        public ImsCallForwardInfo[] newArray(int size) {
+            return new ImsCallForwardInfo[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/ims/ImsCallProfile.aidl b/telephony/java/com/android/ims/ImsCallProfile.aidl
new file mode 100644
index 0000000..a356d13
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsCallProfile.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.android.ims;
+
+parcelable ImsCallProfile;
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
new file mode 100644
index 0000000..208f467
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -0,0 +1,289 @@
+/*
+ * 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 com.android.ims;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Parcelable object to handle IMS call profile.
+ * It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
+ * It provides the service and call type, the additional information related to the call.
+ *
+ * @hide
+ */
+public class ImsCallProfile implements Parcelable {
+    private static final String TAG = "ImsCallProfile";
+
+    /**
+     * Service types
+     */
+    /**
+     * It is for a special case. It helps that the application can make a call
+     * without IMS connection (not registered).
+     * In the moment of the call initiation, the device try to connect to the IMS network
+     * and initiates the call.
+     */
+    public static final int SERVICE_TYPE_NONE = 0;
+    /**
+     * It is a default type and can be selected when the device is connected to the IMS network.
+     */
+    public static final int SERVICE_TYPE_NORMAL = 1;
+    /**
+     * It is for an emergency call.
+     */
+    public static final int SERVICE_TYPE_EMERGENCY = 2;
+
+    /**
+     * Call types
+     */
+    /**
+     * IMSPhone to support IR.92 & IR.94 (voice + video upgrade/downgrade)
+     */
+    public static final int CALL_TYPE_VOICE_N_VIDEO = 1;
+    /**
+     * IR.92 (Voice only)
+     */
+    public static final int CALL_TYPE_VOICE = 2;
+    /**
+     * VT to support IR.92 & IR.94 (voice + video upgrade/downgrade)
+     */
+    public static final int CALL_TYPE_VIDEO_N_VOICE = 3;
+    /**
+     * Video Telephony (audio / video two way)
+     */
+    public static final int CALL_TYPE_VT = 4;
+    /**
+     * Video Telephony (audio two way / video TX one way)
+     */
+    public static final int CALL_TYPE_VT_TX = 5;
+    /**
+     * Video Telephony (audio two way / video RX one way)
+     */
+    public static final int CALL_TYPE_VT_RX = 6;
+    /**
+     * Video Telephony (audio two way / video inactive)
+     */
+    public static final int CALL_TYPE_VT_NODIR = 7;
+    /**
+     * VideoShare (video two way)
+     */
+    public static final int CALL_TYPE_VS = 8;
+    /**
+     * VideoShare (video TX one way)
+     */
+    public static final int CALL_TYPE_VS_TX = 9;
+    /**
+     * VideoShare (video RX one way)
+     */
+    public static final int CALL_TYPE_VS_RX = 10;
+
+    /**
+     * Extra properties for IMS call.
+     */
+    /**
+     * Boolean extra properties - "true" / "false"
+     *  conference : Indicates if the session is for the conference call or not.
+     *  e_call : Indicates if the session is for the emergency call or not.
+     *  vms : Indicates if the session is connected to the voice mail system or not.
+     *  call_mode_changeable : Indicates if the session is able to upgrade/downgrade
+     *      the video during voice call.
+     *  conference_avail : Indicates if the session can be extended to the conference.
+     */
+    public static final String EXTRA_CONFERENCE = "conference";
+    public static final String EXTRA_E_CALL = "e_call";
+    public static final String EXTRA_VMS = "vms";
+    public static final String EXTRA_CALL_MODE_CHANGEABLE = "call_mode_changeable";
+    public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail";
+
+    /**
+     * Integer extra properties
+     *  oir : Rule for originating identity (number) presentation, MO/MT.
+     *      {@link ImsCallProfile#OIR_DEFAULT}
+     *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
+     *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
+     *  cnap : Rule for calling name presentation
+     *      {@link ImsCallProfile#OIR_DEFAULT}
+     *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
+     *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
+     *  dialstring : To identify the Ims call type, MO
+     *      {@link ImsCallProfile#DIALSTRING_NORMAL_CALL}
+     *      {@link ImsCallProfile#DIALSTRING_SS_CONF}
+     *      {@link ImsCallProfile#DIALSTRING_USSD}
+     */
+    public static final String EXTRA_OIR = "oir";
+    public static final String EXTRA_CNAP = "cnap";
+    public static final String EXTRA_DIALSTRING = "dialstring";
+
+    /**
+     * Values for EXTRA_OIR / EXTRA_CNAP
+     */
+    public static final int OIR_DEFAULT = 0;    // "user subscription default value"
+    public static final int OIR_PRESENTATION_RESTRICTED = 1;
+    public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2;
+
+    /**
+     * Values for EXTRA_DIALSTRING
+     */
+    // default (normal call)
+    public static final int DIALSTRING_NORMAL = 0;
+    // Call for SIP-based user configuration
+    public static final int DIALSTRING_SS_CONF = 1;
+    // Call for USSD message
+    public static final int DIALSTRING_USSD = 2;
+
+    /**
+     * String extra properties
+     *  oi : Originating identity (number), MT only
+     *  cna : Calling name
+     *  ussd : For network-initiated USSD, MT only
+     *  remote_uri : Connected user identity (it can be used for the conference)
+     */
+    public static final String EXTRA_OI = "oi";
+    public static final String EXTRA_CNA = "cna";
+    public static final String EXTRA_USSD = "ussd";
+    public static final String EXTRA_REMOTE_URI = "remote_uri";
+
+    public int mServiceType;
+    public int mCallType;
+    public Bundle mCallExtras;
+    public ImsStreamMediaProfile mMediaProfile;
+
+
+
+    public ImsCallProfile(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public ImsCallProfile() {
+        mServiceType = SERVICE_TYPE_NORMAL;
+        mCallType = CALL_TYPE_VOICE_N_VIDEO;
+        mCallExtras = new Bundle();
+        mMediaProfile = new ImsStreamMediaProfile();
+    }
+
+    public ImsCallProfile(int serviceType, int callType) {
+        mServiceType = serviceType;
+        mCallType = callType;
+        mCallExtras = new Bundle();
+        mMediaProfile = new ImsStreamMediaProfile();
+    }
+
+    public String getCallExtra(String name) {
+        return getCallExtra(name, "");
+    }
+
+    public String getCallExtra(String name, String defaultValue) {
+        if (mCallExtras == null) {
+            return defaultValue;
+        }
+
+        return mCallExtras.getString(name, defaultValue);
+    }
+
+    public boolean getCallExtraBoolean(String name) {
+        return getCallExtraBoolean(name, false);
+    }
+
+    public boolean getCallExtraBoolean(String name, boolean defaultValue) {
+        if (mCallExtras == null) {
+            return defaultValue;
+        }
+
+        return mCallExtras.getBoolean(name, defaultValue);
+    }
+
+    public int getCallExtraInt(String name) {
+        return getCallExtraInt(name, -1);
+    }
+
+    public int getCallExtraInt(String name, int defaultValue) {
+        if (mCallExtras == null) {
+            return defaultValue;
+        }
+
+        return mCallExtras.getInt(name, defaultValue);
+    }
+
+    public void setCallExtra(String name, String value) {
+        if (mCallExtras != null) {
+            mCallExtras.putString(name, value);
+        }
+    }
+
+    public void setCallExtraBoolean(String name, boolean value) {
+        if (mCallExtras != null) {
+            mCallExtras.putBoolean(name, value);
+        }
+    }
+
+    public void setCallExtraInt(String name, int value) {
+        if (mCallExtras != null) {
+            mCallExtras.putInt(name, value);
+        }
+    }
+
+    public void updateCallType(ImsCallProfile profile) {
+        mCallType = profile.mCallType;
+    }
+
+    public void updateCallExtras(ImsCallProfile profile) {
+        mCallExtras.clear();
+        mCallExtras = (Bundle) profile.mCallExtras.clone();
+    }
+
+    @Override
+    public String toString() {
+        return "{ serviceType=" + mServiceType +
+                ", callType=" + mCallType +
+                ", callExtras=" + mCallExtras.toString() +
+                ", mediaProfile=" + mMediaProfile.toString() + " }";
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mServiceType);
+        out.writeInt(mCallType);
+        out.writeParcelable(mCallExtras, 0);
+        out.writeParcelable(mMediaProfile, 0);
+    }
+
+    private void readFromParcel(Parcel in) {
+        mServiceType = in.readInt();
+        mCallType = in.readInt();
+        mCallExtras = in.readParcelable(null);
+        mMediaProfile = in.readParcelable(null);
+    }
+
+    public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
+        @Override
+        public ImsCallProfile createFromParcel(Parcel in) {
+            return new ImsCallProfile(in);
+        }
+
+        @Override
+        public ImsCallProfile[] newArray(int size) {
+            return new ImsCallProfile[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/ims/ImsConferenceState.aidl b/telephony/java/com/android/ims/ImsConferenceState.aidl
new file mode 100644
index 0000000..2fc029f
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsConferenceState.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.android.ims;
+
+parcelable ImsConferenceState;
diff --git a/telephony/java/com/android/ims/ImsConferenceState.java b/telephony/java/com/android/ims/ImsConferenceState.java
new file mode 100644
index 0000000..f708d5b
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsConferenceState.java
@@ -0,0 +1,142 @@
+/*
+ * 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 com.android.ims;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Provides the conference information (defined in RFC 4575) for IMS conference call.
+ *
+ * @hide
+ */
+public class ImsConferenceState implements Parcelable {
+    /**
+     * conference-info : user
+     */
+    // user (String) : Tel or SIP URI
+    public static final String USER = "user";
+    // user > display text (String)
+    public static final String DISPLAY_TEXT = "display-text";
+    // user > endpoint (String) : URI or GRUU or Phone number
+    public static final String ENDPOINT = "endpoint";
+    // user > endpoint > status
+    public static final String STATUS = "status";
+
+    /**
+     * status-type (String) :
+     * "pending" : Endpoint is not yet in the session, but it is anticipated that he/she will
+     *      join in the near future.
+     * "dialing-out" : Focus has dialed out to connect the endpoint to the conference,
+     *      but the endpoint is not yet in the roster (probably being authenticated).
+     * "dialing-in" : Endpoint is dialing into the conference, not yet in the roster
+     *      (probably being authenticated).
+     * "alerting" : PSTN alerting or SIP 180 Ringing was returned for the outbound call;
+     *      endpoint is being alerted.
+     * "on-hold" : Active signaling dialog exists between an endpoint and a focus,
+     *      but endpoint is "on-hold" for this conference, i.e., he/she is neither "hearing"
+     *      the conference mix nor is his/her media being mixed in the conference.
+     * "connected" : Endpoint is a participant in the conference. Depending on the media policies,
+     *      he/she can send and receive media to and from other participants.
+     * "disconnecting" : Focus is in the process of disconnecting the endpoint
+     *      (e.g. in SIP a DISCONNECT or BYE was sent to the endpoint).
+     * "disconnected" : Endpoint is not a participant in the conference, and no active dialog
+     *      exists between the endpoint and the focus.
+     * "muted-via-focus" : Active signaling dialog exists beween an endpoint and a focus and
+     *      the endpoint can "listen" to the conference, but the endpoint's media is not being
+     *      mixed into the conference.
+     * "connect-fail" : Endpoint fails to join the conference by rejecting the conference call.
+     */
+    public static final String STATUS_PENDING = "pending";
+    public static final String STATUS_DIALING_OUT = "dialing-out";
+    public static final String STATUS_DIALING_IN = "dialing-in";
+    public static final String STATUS_ALERTING = "alerting";
+    public static final String STATUS_ON_HOLD = "on-hold";
+    public static final String STATUS_CONNECTED = "connected";
+    public static final String STATUS_DISCONNECTING = "disconnecting";
+    public static final String STATUS_DISCONNECTED = "disconnected";
+    public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
+    public static final String STATUS_CONNECT_FAIL = "connect-fail";
+
+    /**
+     * conference-info : SIP status code (integer)
+     */
+    public static final String SIP_STATUS_CODE = "sipstatuscode";
+
+    public HashMap<String, Bundle> mParticipants = new HashMap<String, Bundle>();
+
+    public ImsConferenceState() {
+    }
+
+    public ImsConferenceState(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mParticipants.size());
+
+        if (mParticipants.size() > 0) {
+            Set<Entry<String, Bundle>> entries = mParticipants.entrySet();
+
+            if (entries != null) {
+                Iterator<Entry<String, Bundle>> iterator = entries.iterator();
+
+                while (iterator.hasNext()) {
+                    Entry<String, Bundle> entry = iterator.next();
+
+                    out.writeString(entry.getKey());
+                    out.writeParcelable(entry.getValue(), 0);
+                }
+            }
+        }
+    }
+
+    private void readFromParcel(Parcel in) {
+        int size = in.readInt();
+
+        for (int i = 0; i < size; ++i) {
+            String user = in.readString();
+            Bundle state = in.readParcelable(null);
+            mParticipants.put(user, state);
+        }
+    }
+
+    public static final Creator<ImsConferenceState> CREATOR =
+            new Creator<ImsConferenceState>() {
+        @Override
+        public ImsConferenceState createFromParcel(Parcel in) {
+            return new ImsConferenceState(in);
+        }
+
+        @Override
+        public ImsConferenceState[] newArray(int size) {
+            return new ImsConferenceState[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.aidl b/telephony/java/com/android/ims/ImsReasonInfo.aidl
new file mode 100644
index 0000000..17e6d3a
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsReasonInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.android.ims;
+
+parcelable ImsReasonInfo;
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
new file mode 100644
index 0000000..99faba6
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -0,0 +1,326 @@
+/*
+ * 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 com.android.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class enables an application to get details on why a method call failed.
+ *
+ * @hide
+ */
+public class ImsReasonInfo implements Parcelable {
+
+    /**
+     * Reason types, defines the error category.
+     *    UNSPECIFIED - unknown error reason
+     *    LOCAL - indicates the local/device error reason
+     *    LOCAL_TIMEOUT - indicates the local error reason when a specific timer is expired
+     *    STATUSCODE - indicates the interworking error reason by SIP status code received
+     *        from the network
+     *    MEDIA - indicates the media error reason (local resource, SDP parameter, etc.)
+     *    USER - indicates the error reason by the local or remote user
+     *    UT - indicates the error reason for the supplementary service configuration
+     */
+    public static final int TYPE_UNSPECIFIED = 0;
+    public static final int TYPE_LOCAL = 1;
+    public static final int TYPE_TIMEOUT = 2;
+    public static final int TYPE_STATUSCODE = 3;
+    public static final int TYPE_MEDIA = 4;
+    public static final int TYPE_USER = 5;
+    public static final int TYPE_UT = 8;
+
+    /**
+     * Specific code of each types
+     */
+    public static final int CODE_UNSPECIFIED = 0;
+
+    /**
+     * LOCAL
+     */
+    // IMS -> Telephony
+    // The passed argument is an invalid
+    public static final int CODE_LOCAL_ILLEGAL_ARGUMENT = 101;
+    // The operation is invoked in invalid call state
+    public static final int CODE_LOCAL_ILLEGAL_STATE = 102;
+    // IMS service internal error
+    public static final int CODE_LOCAL_INTERNAL_ERROR = 103;
+    // IMS service goes down (service connection is lost)
+    public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106;
+    // No pending incoming call exists
+    public static final int CODE_LOCAL_NO_PENDING_CALL = 107;
+
+    // IMS -> Telephony
+    // Service unavailable; by power off
+    public static final int CODE_LOCAL_POWER_OFF = 111;
+    // Service unavailable; by low battery
+    public static final int CODE_LOCAL_LOW_BATTERY = 112;
+    // Service unavailable; by out of service (data service state)
+    public static final int CODE_LOCAL_NETWORK_NO_SERVICE = 121;
+    // Service unavailable; by no LTE coverage
+    // (VoLTE is not supported even though IMS is registered)
+    public static final int CODE_LOCAL_NETWORK_NO_LTE_COVERAGE = 122;
+    // Service unavailable; by located in roaming area
+    public static final int CODE_LOCAL_NETWORK_ROAMING = 123;
+    // Service unavailable; by IP changed
+    public static final int CODE_LOCAL_NETWORK_IP_CHANGED = 124;
+    // Service unavailable; other
+    public static final int CODE_LOCAL_SERVICE_UNAVAILABLE = 131;
+    // Service unavailable; IMS connection is lost (IMS is not registered)
+    public static final int CODE_LOCAL_NOT_REGISTERED = 132;
+
+    // IMS <-> Telephony
+    // Max call exceeded
+    public static final int CODE_LOCAL_CALL_EXCEEDED = 141;
+    // IMS <- Telephony
+    // Call busy
+    public static final int CODE_LOCAL_CALL_BUSY = 142;
+    // Call decline
+    public static final int CODE_LOCAL_CALL_DECLINE = 143;
+    // IMS -> Telephony
+    // SRVCC is in progress
+    public static final int CODE_LOCAL_CALL_VCC_ON_PROGRESSING = 144;
+    // Resource reservation is failed (QoS precondition)
+    public static final int CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED = 145;
+    // Retry CS call; VoLTE service can't be provided by the network or remote end
+    // Resolve the extra code(EXTRA_CODE_CALL_RETRY_*) if the below code is set
+    public static final int CODE_LOCAL_CALL_CS_RETRY_REQUIRED = 146;
+    // Retry VoLTE call; VoLTE service can't be provided by the network temporarily
+    public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147;
+    // IMS call is already terminated (in TERMINATED state)
+    public static final int CODE_LOCAL_CALL_TERMINATED = 148;
+
+    /**
+     * TIMEOUT (IMS -> Telephony)
+     */
+    // 1xx waiting timer is expired after sending INVITE request (MO only)
+    public static final int CODE_TIMEOUT_1XX_WAITING = 201;
+    // User no answer during call setup operation (MO/MT)
+    // MO : 200 OK to INVITE request is not received,
+    // MT : No action from user after alerting the call
+    public static final int CODE_TIMEOUT_NO_ANSWER = 202;
+    // User no answer during call update operation (MO/MT)
+    // MO : 200 OK to re-INVITE request is not received,
+    // MT : No action from user after alerting the call
+    public static final int CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE = 203;
+
+    /**
+     * STATUSCODE (SIP response code) (IMS -> Telephony)
+     */
+    // 3xx responses
+    // SIP request is redirected
+    public static final int CODE_SIP_REDIRECTED = 321;
+    // 4xx responses
+    // 400 : Bad Request
+    public static final int CODE_SIP_BAD_REQUEST = 331;
+    // 403 : Forbidden
+    public static final int CODE_SIP_FORBIDDEN = 332;
+    // 404 : Not Found
+    public static final int CODE_SIP_NOT_FOUND = 333;
+    // 415 : Unsupported Media Type
+    // 416 : Unsupported URI Scheme
+    // 420 : Bad Extension
+    public static final int CODE_SIP_NOT_SUPPORTED = 334;
+    // 408 : Request Timeout
+    public static final int CODE_SIP_REQUEST_TIMEOUT = 335;
+    // 480 : Temporarily Unavailable
+    public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336;
+    // 484 : Address Incomplete
+    public static final int CODE_SIP_BAD_ADDRESS = 337;
+    // 486 : Busy Here
+    // 600 : Busy Everywhere
+    public static final int CODE_SIP_BUSY = 338;
+    // 487 : Request Terminated
+    public static final int CODE_SIP_REQUEST_CANCELLED = 339;
+    // 406 : Not Acceptable
+    // 488 : Not Acceptable Here
+    // 606 : Not Acceptable
+    public static final int CODE_SIP_NOT_ACCEPTABLE = 340;
+    // 410 : Gone
+    // 604 : Does Not Exist Anywhere
+    public static final int CODE_SIP_NOT_REACHABLE = 341;
+    // Others
+    public static final int CODE_SIP_CLIENT_ERROR = 342;
+    // 5xx responses
+    // 501 : Server Internal Error
+    public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351;
+    // 503 : Service Unavailable
+    public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352;
+    // 504 : Server Time-out
+    public static final int CODE_SIP_SERVER_TIMEOUT = 353;
+    // Others
+    public static final int CODE_SIP_SERVER_ERROR = 354;
+    // 6xx responses
+    // 603 : Decline
+    public static final int CODE_SIP_USER_REJECTED = 361;
+    // Others
+    public static final int CODE_SIP_GLOBAL_ERROR = 362;
+
+    /**
+     * MEDIA (IMS -> Telephony)
+     */
+    // Media resource initialization failed
+    public static final int CODE_MEDIA_INIT_FAILED = 401;
+    // RTP timeout (no audio / video traffic in the session)
+    public static final int CODE_MEDIA_NO_DATA = 402;
+    // Media is not supported; so dropped the call
+    public static final int CODE_MEDIA_NOT_ACCEPTABLE = 403;
+    // Unknown media related errors
+    public static final int CODE_MEDIA_UNSPECIFIED = 404;
+
+    /**
+     * USER
+     */
+    // Telephony -> IMS
+    // User triggers the call end
+    public static final int CODE_USER_TERMINATED = 501;
+    // No action while an incoming call is ringing
+    public static final int CODE_USER_NOANSWER = 502;
+    // User ignores an incoming call
+    public static final int CODE_USER_IGNORE = 503;
+    // User declines an incoming call
+    public static final int CODE_USER_DECLINE = 504;
+    // IMS -> Telephony
+    // The call is terminated by the network or remote user
+    public static final int CODE_USER_TERMINATED_BY_REMOTE = 510;
+
+    /**
+     * Extra codes for the specific code value
+     * This value can be referred when the code is CODE_LOCAL_CALL_CS_RETRY_REQUIRED.
+     */
+    // Try to connect CS call; normal
+    public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1;
+    // Try to connect CS call without the notification to user
+    public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2;
+    // Try to connect CS call by the settings of the menu
+    public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3;
+
+    /**
+     * UT
+     */
+    public static final int CODE_UT_NOT_SUPPORTED = 801;
+    public static final int CODE_UT_SERVICE_UNAVAILABLE = 802;
+    public static final int CODE_UT_OPERATION_NOT_ALLOWED = 803;
+    public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821;
+
+
+
+    // For reason type
+    public int mReasonType;
+    // For main reason code
+    public int mCode;
+    // For the extra code value; it depends on the code value.
+    public int mExtraCode;
+    // For the additional message of the reason info.
+    public String mExtraMessage;
+
+    public ImsReasonInfo() {
+        mReasonType = TYPE_UNSPECIFIED;
+        mCode = CODE_UNSPECIFIED;
+        mExtraCode = CODE_UNSPECIFIED;
+        mExtraMessage = null;
+    }
+
+    public ImsReasonInfo(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public ImsReasonInfo(int code, int extraCode) {
+        mReasonType = (int) (code / 100);
+        mCode = code;
+        mExtraCode = extraCode;
+        mExtraMessage = null;
+    }
+
+    public ImsReasonInfo(int code, int extraCode, String extraMessage) {
+        mReasonType = (int) (code / 100);
+        mCode = code;
+        mExtraCode = extraCode;
+        mExtraMessage = extraMessage;
+    }
+
+    /**
+     *
+     */
+    public int getCode() {
+        return mCode;
+    }
+
+    /**
+     *
+     */
+    public int getExtraCode() {
+        return mExtraCode;
+    }
+
+    /**
+     *
+     */
+    public String getExtraMessage() {
+        return mExtraMessage;
+    }
+
+    /**
+     *
+     */
+    public int getReasonType() {
+        return mReasonType;
+    }
+
+    /**
+     * Returns the string format of {@link ImsReasonInfo}
+     *
+     * @return the string format of {@link ImsReasonInfo}
+     */
+    public String toString() {
+        return "ImsReasonInfo :: {" + mReasonType + ", "
+                + mCode + ", " + mExtraCode + ", " + mExtraMessage + "}";
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mReasonType);
+        out.writeInt(mCode);
+        out.writeInt(mExtraCode);
+        out.writeString(mExtraMessage);
+    }
+
+    private void readFromParcel(Parcel in) {
+        mReasonType = in.readInt();
+        mCode = in.readInt();
+        mExtraCode = in.readInt();
+        mExtraMessage = in.readString();
+    }
+
+    public static final Creator<ImsReasonInfo> CREATOR = new Creator<ImsReasonInfo>() {
+        @Override
+        public ImsReasonInfo createFromParcel(Parcel in) {
+            return new ImsReasonInfo(in);
+        }
+
+        @Override
+        public ImsReasonInfo[] newArray(int size) {
+            return new ImsReasonInfo[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/ims/ImsSsInfo.aidl b/telephony/java/com/android/ims/ImsSsInfo.aidl
new file mode 100644
index 0000000..0ac598b
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsSsInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.android.ims;
+
+parcelable ImsSsInfo;
diff --git a/telephony/java/com/android/ims/ImsSsInfo.java b/telephony/java/com/android/ims/ImsSsInfo.java
new file mode 100644
index 0000000..dbde1c6
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsSsInfo.java
@@ -0,0 +1,76 @@
+/*
+ * 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 com.android.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Provides the result to the update operation for the supplementary service configuration.
+ *
+ * @hide
+ */
+public class ImsSsInfo implements Parcelable {
+    /**
+     * For the status of service registration or activation/deactivation.
+     */
+    public static final int NOT_REGISTERED = (-1);
+    public static final int DISABLED = 0;
+    public static final int ENABLED = 1;
+
+    // 0: disabled, 1: enabled
+    public int mStatus;
+
+    public ImsSsInfo() {
+    }
+
+    public ImsSsInfo(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mStatus);
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled");
+    }
+
+    private void readFromParcel(Parcel in) {
+        mStatus = in.readInt();
+    }
+
+    public static final Creator<ImsSsInfo> CREATOR =
+            new Creator<ImsSsInfo>() {
+        @Override
+        public ImsSsInfo createFromParcel(Parcel in) {
+            return new ImsSsInfo(in);
+        }
+
+        @Override
+        public ImsSsInfo[] newArray(int size) {
+            return new ImsSsInfo[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl b/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
new file mode 100644
index 0000000..d648a35
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsStreamMediaProfile.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.android.ims;
+
+parcelable ImsStreamMediaProfile;
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.java b/telephony/java/com/android/ims/ImsStreamMediaProfile.java
new file mode 100644
index 0000000..003499c
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsStreamMediaProfile.java
@@ -0,0 +1,132 @@
+/*
+ * 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 com.android.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Parcelable object to handle IMS stream media profile.
+ * It provides the media direction, quality of audio and/or video.
+ *
+ * @hide
+ */
+public class ImsStreamMediaProfile implements Parcelable {
+    private static final String TAG = "ImsStreamMediaProfile";
+
+    /**
+     * Media directions
+     */
+    public static final int DIRECTION_INVALID = (-1);
+    public static final int DIRECTION_INACTIVE = 0;
+    public static final int DIRECTION_RECEIVE = 1;
+    public static final int DIRECTION_SEND = 2;
+    public static final int DIRECTION_SEND_RECEIVE = 3;
+
+    /**
+     * Audio information
+     */
+    public static final int AUDIO_QUALITY_NONE = 0;
+    public static final int AUDIO_QUALITY_AMR = (1 << 0);
+    public static final int AUDIO_QUALITY_AMR_WB = (1 << 1);
+
+    /**
+     * Video information
+     */
+    public static final int VIDEO_QUALITY_NONE = 0;
+    public static final int VIDEO_QUALITY_QCIF = (1 << 0);
+    public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = (1 << 1);
+    public static final int VIDEO_QUALITY_QVGA_PORTRAIT = (1 << 2);
+    public static final int VIDEO_QUALITY_VGA_LANDSCAPE = (1 << 3);
+    public static final int VIDEO_QUALITY_VGA_PORTRAIT = (1 << 4);
+
+    // Audio related information
+    public int mAudioQuality;
+    public int mAudioDirection;
+    // Video related information
+    public int mVideoQuality;
+    public int mVideoDirection;
+
+
+
+    public ImsStreamMediaProfile(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public ImsStreamMediaProfile() {
+        mAudioQuality = AUDIO_QUALITY_AMR_WB;
+        mAudioDirection = DIRECTION_SEND_RECEIVE;
+        mVideoQuality = VIDEO_QUALITY_NONE;
+        mVideoDirection = DIRECTION_INVALID;
+    }
+
+    public ImsStreamMediaProfile(int audioQuality, int audioDirection,
+            int videoQuality, int videoDirection) {
+        mAudioQuality = audioQuality;
+        mAudioDirection = audioDirection;
+        mVideoQuality = videoQuality;
+        mVideoDirection = videoDirection;
+    }
+
+    public void copyFrom(ImsStreamMediaProfile profile) {
+        mAudioQuality = profile.mAudioQuality;
+        mAudioDirection = profile.mAudioDirection;
+        mVideoQuality = profile.mVideoQuality;
+        mVideoDirection = profile.mVideoDirection;
+    }
+
+    @Override
+    public String toString() {
+        return "{ audioQuality=" + mAudioQuality +
+                ", audioDirection=" + mAudioDirection +
+                ", videoQuality=" + mVideoQuality +
+                ", videoDirection=" + mVideoDirection + " }";
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mAudioQuality);
+        out.writeInt(mAudioDirection);
+        out.writeInt(mVideoQuality);
+        out.writeInt(mVideoDirection);
+    }
+
+    private void readFromParcel(Parcel in) {
+        mAudioQuality = in.readInt();
+        mAudioDirection = in.readInt();
+        mVideoQuality = in.readInt();
+        mVideoDirection = in.readInt();
+    }
+
+    public static final Creator<ImsStreamMediaProfile> CREATOR =
+            new Creator<ImsStreamMediaProfile>() {
+        @Override
+        public ImsStreamMediaProfile createFromParcel(Parcel in) {
+            return new ImsStreamMediaProfile(in);
+        }
+
+        @Override
+        public ImsStreamMediaProfile[] newArray(int size) {
+            return new ImsStreamMediaProfile[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
new file mode 100644
index 0000000..5f2ff36
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
@@ -0,0 +1,219 @@
+/*
+ * 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 com.android.ims.internal;
+
+import com.android.ims.ImsCallProfile;
+import com.android.ims.ImsStreamMediaProfile;
+import com.android.ims.internal.IImsCallSessionListener;
+
+/**
+ * An IMS session that is associated with a SIP dialog which is established from/to
+ * INVITE request or a mid-call transaction to control the session.
+ * {@hide}
+ */
+interface IImsCallSession {
+    /**
+     * Closes the object. This object is not usable after being closed.
+     */
+    void close();
+
+    /**
+     * Gets the call ID of the session.
+     *
+     * @return the call ID
+     */
+    String getCallId();
+
+    /**
+     * Gets the call profile that this session is associated with
+     *
+     * @return the call profile that this session is associated with
+     */
+    ImsCallProfile getCallProfile();
+
+    /**
+     * Gets the local call profile that this session is associated with
+     *
+     * @return the local call profile that this session is associated with
+     */
+    ImsCallProfile getLocalCallProfile();
+
+    /**
+     * Gets the value associated with the specified property of this session.
+     *
+     * @return the string value associated with the specified property
+     */
+    String getProperty(String name);
+
+    /**
+     * Gets the session state. The value returned must be one of the states in
+     * {@link ImsCallSession#State}.
+     *
+     * @return the session state
+     */
+    int getState();
+
+    /**
+     * Checks if the session is in a call.
+     *
+     * @return true if the session is in a call
+     */
+    boolean isInCall();
+
+    /**
+     * Sets the listener to listen to the session events. A {@link IImsCallSession}
+     * can only hold one listener at a time. Subsequent calls to this method
+     * override the previous listener.
+     *
+     * @param listener to listen to the session events of this object
+     */
+    void setListener(in IImsCallSessionListener listener);
+
+    /**
+     * Mutes or unmutes the mic for the active call.
+     *
+     * @param muted true if the call is muted, false otherwise
+     */
+    void setMute(boolean muted);
+
+    /**
+     * Initiates an IMS call with the specified target and call profile.
+     * The session listener is called back upon defined session events.
+     * The method is only valid to call when the session state is in
+     * {@link ImsCallSession#State#IDLE}.
+     *
+     * @param callee dialed string to make the call to
+     * @param profile call profile to make the call with the specified service type,
+     *      call type and media information
+     * @see Listener#callSessionStarted, Listener#callSessionStartFailed
+     */
+    void start(String callee, in ImsCallProfile profile);
+
+    /**
+     * Initiates an IMS call with the specified participants and call profile.
+     * The session listener is called back upon defined session events.
+     * The method is only valid to call when the session state is in
+     * {@link ImsCallSession#State#IDLE}.
+     *
+     * @param participants participant list to initiate an IMS conference call
+     * @param profile call profile to make the call with the specified service type,
+     *      call type and media information
+     * @see Listener#callSessionStarted, Listener#callSessionStartFailed
+     */
+    void startConference(in String[] participants, in ImsCallProfile profile);
+
+    /**
+     * Accepts an incoming call or session update.
+     *
+     * @param callType call type specified in {@link ImsCallProfile} to be answered
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
+     * @see Listener#callSessionStarted
+     */
+    void accept(int callType, in ImsStreamMediaProfile profile);
+
+    /**
+     * Rejects an incoming call or session update.
+     *
+     * @param reason reason code to reject an incoming call
+     * @see Listener#callSessionStartFailed
+     */
+    void reject(int reason);
+
+    /**
+     * Terminates a call.
+     *
+     * @see Listener#callSessionTerminated
+     */
+    void terminate(int reason);
+
+    /**
+     * Puts a call on hold. When it succeeds, {@link Listener#callSessionHeld} is called.
+     *
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
+     * @see Listener#callSessionHeld, Listener#callSessionHoldFailed
+     */
+    void hold(in ImsStreamMediaProfile profile);
+
+    /**
+     * Continues a call that's on hold. When it succeeds, {@link Listener#callSessionResumed}
+     * is called.
+     *
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to resume the call
+     * @see Listener#callSessionResumed, Listener#callSessionResumeFailed
+     */
+    void resume(in ImsStreamMediaProfile profile);
+
+    /**
+     * Merges the active & hold call. When it succeeds, {@link Listener#callSessionMerged}
+     * is called.
+     *
+     * @see Listener#callSessionMerged, Listener#callSessionMergeFailed
+     */
+    void merge();
+
+    /**
+     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
+     *
+     * @param callType call type specified in {@link ImsCallProfile} to be updated
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated
+     * @see Listener#callSessionUpdated, Listener#callSessionUpdateFailed
+     */
+    void update(int callType, in ImsStreamMediaProfile profile);
+
+    /**
+     * Extends this call to the conference call with the specified recipients.
+     *
+     * @param participants participant list to be invited to the conference call after extending the call
+     * @see Listener#sessionConferenceExtened, Listener#sessionConferenceExtendFailed
+     */
+    void extendToConference(in String[] participants);
+
+    /**
+     * Requests the conference server to invite an additional participants to the conference.
+     *
+     * @param participants participant list to be invited to the conference call
+     * @see Listener#sessionInviteParticipantsRequestDelivered,
+     *      Listener#sessionInviteParticipantsRequestFailed
+     */
+    void inviteParticipants(in String[] participants);
+
+    /**
+     * Requests the conference server to remove the specified participants from the conference.
+     *
+     * @param participants participant list to be removed from the conference call
+     * @see Listener#sessionRemoveParticipantsRequestDelivered,
+     *      Listener#sessionRemoveParticipantsRequestFailed
+     */
+    void removeParticipants(in String[] participants);
+
+    /**
+     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
+     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
+     * and event flash to 16. Currently, event flash is not supported.
+     *
+     * @param code the DTMF to send. Value 0 to 15 (inclusive) are valid inputs.
+     * @param duration the interval in milli-seconds between the DTMFs
+     */
+    void sendDtmf(int code, int duration);
+
+    /**
+     * Sends an USSD message.
+     *
+     * @param ussdMessage USSD message to send
+     */
+    void sendUssd(String ussdMessage);
+}
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
new file mode 100644
index 0000000..f36cf39
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -0,0 +1,99 @@
+/*
+ * 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 com.android.ims.internal;
+
+import com.android.ims.ImsStreamMediaProfile;
+import com.android.ims.ImsCallProfile;
+import com.android.ims.ImsReasonInfo;
+import com.android.ims.ImsConferenceState;
+import com.android.ims.internal.IImsCallSession;
+
+/**
+ * A listener type for receiving notification on IMS call session events.
+ * When an event is generated for an {@link IImsCallSession}, the application is notified
+ * by having one of the methods called on the {@link IImsCallSessionListener}.
+ * {@hide}
+ */
+interface IImsCallSessionListener {
+    /**
+     * Notifies the result of the basic session operation (setup / terminate).
+     */
+    void callSessionProgressing(in IImsCallSession session, in ImsStreamMediaProfile profile);
+    void callSessionStarted(in IImsCallSession session, in ImsCallProfile profile);
+    void callSessionStartFailed(in IImsCallSession session, in ImsReasonInfo reasonInfo);
+    void callSessionTerminated(in IImsCallSession session, in ImsReasonInfo reasonInfo);
+
+    /**
+     * Notifies the result of the call hold/resume operation.
+     */
+    void callSessionHeld(in IImsCallSession session, in ImsCallProfile profile);
+    void callSessionHoldFailed(in IImsCallSession session, in ImsReasonInfo reasonInfo);
+    void callSessionHoldReceived(in IImsCallSession session, in ImsCallProfile profile);
+    void callSessionResumed(in IImsCallSession session, in ImsCallProfile profile);
+    void callSessionResumeFailed(in IImsCallSession session, in ImsReasonInfo reasonInfo);
+    void callSessionResumeReceived(in IImsCallSession session, in ImsCallProfile profile);
+
+    /**
+     * Notifiies the result of call merge operation.
+     */
+    void callSessionMerged(in IImsCallSession session,
+            in IImsCallSession newSession, in ImsCallProfile profile);
+    void callSessionMergeFailed(in IImsCallSession session,
+            in ImsReasonInfo reasonInfo);
+
+    /**
+     * Notifies the result of call upgrade / downgrade or any other call updates.
+     */
+    void callSessionUpdated(in IImsCallSession session,
+            in ImsCallProfile profile);
+    void callSessionUpdateFailed(in IImsCallSession session,
+            in ImsReasonInfo reasonInfo);
+    void callSessionUpdateReceived(in IImsCallSession session,
+            in ImsCallProfile profile);
+
+    /**
+     * Notifies the result of conference extension.
+     */
+    void callSessionConferenceExtended(in IImsCallSession session,
+            in IImsCallSession newSession, in ImsCallProfile profile);
+    void callSessionConferenceExtendFailed(in IImsCallSession session,
+            in ImsReasonInfo reasonInfo);
+    void callSessionConferenceExtendReceived(in IImsCallSession session,
+            in IImsCallSession newSession, in ImsCallProfile profile);
+
+    /**
+     * Notifies the result of the participant invitation / removal to/from the conference session.
+     */
+    void callSessionInviteParticipantsRequestDelivered(in IImsCallSession session);
+    void callSessionInviteParticipantsRequestFailed(in IImsCallSession session,
+            in ImsReasonInfo reasonInfo);
+    void callSessionRemoveParticipantsRequestDelivered(in IImsCallSession session);
+    void callSessionRemoveParticipantsRequestFailed(in IImsCallSession session,
+            in ImsReasonInfo reasonInfo);
+
+    /**
+     * Notifies the changes of the conference info. in the conference session.
+     */
+    void callSessionConferenceStateUpdated(in IImsCallSession session,
+            in ImsConferenceState state);
+
+    /**
+     * Notifies the incoming USSD message.
+     */
+    void callSessionUssdMessageReceived(in IImsCallSession session,
+            int mode, String ussdMessage);
+}
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
new file mode 100644
index 0000000..5f243a0
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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 com.android.ims.internal;
+
+/**
+ * A listener type for receiving notifications about the changes to
+ * the IMS connection(registration).
+ *
+ * {@hide}
+ */
+interface IImsRegistrationListener {
+    /**
+     * Notifies the application when the device is connected to the IMS network.
+     */
+    void registrationConnected();
+
+    /**
+     * Notifies the application when the device is disconnected from the IMS network.
+     */
+    void registrationDisconnected();
+
+    /**
+     * Notifies the application when its suspended IMS connection is resumed,
+     * meaning the connection now allows throughput.
+     */
+    void registrationResumed();
+
+    /**
+     * Notifies the application when its current IMS connection is suspended,
+     * meaning there is no data throughput.
+     */
+    void registrationSuspended();
+
+    /**
+     * Notifies the application when its current IMS connection is updated
+     * since the service setting is changed or the service is added/removed.
+     *
+     * @param serviceClass a service class specified in {@link ImsServiceClass}
+     * @param event an event type when this callback is called
+     *    If {@code event} is 0, meaning the specified service is removed from the IMS connection.
+     *    Else ({@code event} is 1), meaning the specified service is added to the IMS connection.
+     */
+    void registrationServiceCapabilityChanged(int serviceClass, int event);
+}
diff --git a/telephony/java/com/android/ims/internal/IImsService.aidl b/telephony/java/com/android/ims/internal/IImsService.aidl
new file mode 100644
index 0000000..bac5651
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsService.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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 com.android.ims.internal;
+
+import android.app.PendingIntent;
+
+import com.android.ims.ImsCallProfile;
+import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsCallSessionListener;
+import com.android.ims.internal.IImsUt;
+
+/**
+ * {@hide}
+ */
+interface IImsService {
+    int open(int serviceClass, in PendingIntent incomingCallIntent,
+            in IImsRegistrationListener listener);
+    void close(int serviceId);
+    boolean isConnected(int serviceId, int serviceType, int callType);
+    boolean isOpened(int serviceId);
+    void setRegistrationListener(int serviceId, in IImsRegistrationListener listener);
+
+    ImsCallProfile createCallProfile(int serviceId, int serviceType, int callType);
+
+    IImsCallSession createCallSession(int serviceId, in ImsCallProfile profile,
+            in IImsCallSessionListener listener);
+    IImsCallSession getPendingCallSession(int serviceId, String callId);
+
+    /**
+     * Ut interface for the supplementary service configuration.
+     */
+    IImsUt getUtInterface(int serviceId);
+}
diff --git a/telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl b/telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl
new file mode 100644
index 0000000..459c685
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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 com.android.ims.internal;
+
+/**
+ *
+ * {@hide}
+ */
+interface IImsStreamMediaSession {
+    void close();
+}
diff --git a/telephony/java/com/android/ims/internal/IImsUt.aidl b/telephony/java/com/android/ims/internal/IImsUt.aidl
new file mode 100644
index 0000000..32929ed
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsUt.aidl
@@ -0,0 +1,73 @@
+/*
+ * 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 com.android.ims.internal;
+
+import android.os.Bundle;
+
+import com.android.ims.internal.IImsUtListener;
+
+/**
+ * Provides the Ut interface interworking to get/set the supplementary service configuration.
+ *
+ * {@hide}
+ */
+interface IImsUt {
+    /**
+     * Closes the object. This object is not usable after being closed.
+     */
+    void close();
+
+    /**
+     * Retrieves the configuration of the call barring.
+     */
+    int queryCallBarring(int cbType);
+
+    /**
+     * Retrieves the configuration of the call forward.
+     */
+    int queryCallForward(int condition, String number);
+
+    /**
+     * Retrieves the configuration of the call waiting.
+     */
+    int queryCallWaiting();
+
+    /**
+     * Updates or retrieves the supplementary service configuration.
+     */
+    int transact(in Bundle ssInfo);
+
+    /**
+     * Updates the configuration of the call barring.
+     */
+    int updateCallBarring(int cbType, boolean enable);
+
+    /**
+     * Updates the configuration of the call forward.
+     */
+    int updateCallForward(int action, int condition, String number, int timeSeconds);
+
+    /**
+     * Updates the configuration of the call waiting.
+     */
+    int updateCallWaiting(boolean enable);
+
+    /**
+     * Sets the listener.
+     */
+    void setListener(in IImsUtListener listener);
+}
diff --git a/telephony/java/com/android/ims/internal/IImsUtListener.aidl b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
new file mode 100644
index 0000000..3f1b5a7
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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 com.android.ims.internal;
+
+import android.os.Bundle;
+
+import com.android.ims.ImsCallForwardInfo;
+import com.android.ims.ImsSsInfo;
+import com.android.ims.internal.IImsUt;
+
+/**
+ * {@hide}
+ */
+interface IImsUtListener {
+    /**
+     * Notifies the result of the supplementary service configuration udpate.
+     */
+    void utConfigurationUpdated(in IImsUt ut, int id);
+    void utConfigurationUpdateFailed(in IImsUt ut, int id, int errorCode);
+
+    /**
+     * Notifies the result of the supplementary service configuration query.
+     */
+    void utConfigurationQueried(in IImsUt ut, int id, in Bundle ssInfo);
+    void utConfigurationQueryFailed(in IImsUt ut, int id, int errorCode);
+
+    /**
+     * Notifies the status of the call barring supplementary service.
+     */
+    void utConfigurationCallBarringQueried(in IImsUt ut,
+            int id, in ImsSsInfo[] cbInfo);
+
+    /**
+     * Notifies the status of the call forwarding supplementary service.
+     */
+    void utConfigurationCallForwardQueried(in IImsUt ut,
+            int id, in ImsCallForwardInfo[] cfInfo);
+
+    /**
+     * Notifies the status of the call waiting supplementary service.
+     */
+    void utConfigurationCallWaitingQueried(in IImsUt ut,
+            int id, in ImsSsInfo[] cwInfo);
+}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 1d10729..59036da 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -305,6 +305,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
         throw new UnsupportedOperationException();
diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
index 1c9c40d..ee2e895 100644
--- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
+++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl
@@ -26,6 +26,7 @@
 interface IWifiP2pManager
 {
     Messenger getMessenger();
+    Messenger getP2pStateMachineMessenger();
     void setMiracastMode(int mode);
 }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 3ed2406..6409450 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -276,6 +276,13 @@
     public static final String WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION =
         "android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED";
 
+    /**
+     * The lookup key for a handover message returned by the WifiP2pService.
+     * @hide
+     */
+    public static final String EXTRA_HANDOVER_MESSAGE =
+            "android.net.wifi.p2p.EXTRA_HANDOVER_MESSAGE";
+
     IWifiP2pManager mService;
 
     private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
@@ -446,6 +453,21 @@
     /** @hide */
     public static final int SET_CHANNEL_SUCCEEDED                   = BASE + 73;
 
+    /** @hide */
+    public static final int GET_HANDOVER_REQUEST                    = BASE + 75;
+    /** @hide */
+    public static final int GET_HANDOVER_SELECT                     = BASE + 76;
+    /** @hide */
+    public static final int RESPONSE_GET_HANDOVER_MESSAGE           = BASE + 77;
+    /** @hide */
+    public static final int INITIATOR_REPORT_NFC_HANDOVER           = BASE + 78;
+    /** @hide */
+    public static final int RESPONDER_REPORT_NFC_HANDOVER           = BASE + 79;
+    /** @hide */
+    public static final int REPORT_NFC_HANDOVER_SUCCEEDED           = BASE + 80;
+    /** @hide */
+    public static final int REPORT_NFC_HANDOVER_FAILED              = BASE + 81;
+
 
     /**
      * Create a new WifiP2pManager instance. Applications use
@@ -627,6 +649,14 @@
     }
 
     /**
+     * Interface for callback invocation when Handover Request or Select Message is available
+     * @hide
+     */
+    public interface HandoverMessageListener {
+        public void onHandoverMessageAvailable(String handoverMessage);
+    }
+
+    /**
      * A channel that connects the application to the Wifi p2p framework.
      * Most p2p operations require a Channel as an argument. An instance of Channel is obtained
      * by doing a call on {@link #initialize}
@@ -687,6 +717,7 @@
                     case START_LISTEN_FAILED:
                     case STOP_LISTEN_FAILED:
                     case SET_CHANNEL_FAILED:
+                    case REPORT_NFC_HANDOVER_FAILED:
                         if (listener != null) {
                             ((ActionListener) listener).onFailure(message.arg1);
                         }
@@ -712,6 +743,7 @@
                     case START_LISTEN_SUCCEEDED:
                     case STOP_LISTEN_SUCCEEDED:
                     case SET_CHANNEL_SUCCEEDED:
+                    case REPORT_NFC_HANDOVER_SUCCEEDED:
                         if (listener != null) {
                             ((ActionListener) listener).onSuccess();
                         }
@@ -745,7 +777,17 @@
                                 onPersistentGroupInfoAvailable(groups);
                         }
                         break;
-                   default:
+                    case RESPONSE_GET_HANDOVER_MESSAGE:
+                        Bundle handoverBundle = (Bundle) message.obj;
+                        if (listener != null) {
+                            String handoverMessage = handoverBundle != null
+                                    ? handoverBundle.getString(EXTRA_HANDOVER_MESSAGE)
+                                    : null;
+                            ((HandoverMessageListener) listener)
+                                    .onHandoverMessageAvailable(handoverMessage);
+                        }
+                        break;
+                    default:
                         Log.d(TAG, "Ignored " + message);
                         break;
                 }
@@ -841,7 +883,20 @@
      * @return Channel instance that is necessary for performing any further p2p operations
      */
     public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
-        Messenger messenger = getMessenger();
+        return initalizeChannel(srcContext, srcLooper, listener, getMessenger());
+    }
+
+    /**
+     * Registers the application with the Wi-Fi framework. Enables system-only functionality.
+     * @hide
+     */
+    public Channel initializeInternal(Context srcContext, Looper srcLooper,
+                                      ChannelListener listener) {
+        return initalizeChannel(srcContext, srcLooper, listener, getP2pStateMachineMessenger());
+    }
+
+    private Channel initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener,
+                                     Messenger messenger) {
         if (messenger == null) return null;
 
         Channel c = new Channel(srcContext, srcLooper, listener);
@@ -1327,4 +1382,62 @@
         }
     }
 
+    /**
+     * Get a reference to P2pStateMachine handler. This is used to establish
+     * a priveleged AsyncChannel communication with WifiP2pService.
+     *
+     * @return Messenger pointing to the WifiP2pService handler
+     * @hide
+     */
+    public Messenger getP2pStateMachineMessenger() {
+        try {
+            return mService.getP2pStateMachineMessenger();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Get a handover request message for use in WFA NFC Handover transfer.
+     * @hide
+     */
+    public void getNfcHandoverRequest(Channel c, HandoverMessageListener listener) {
+        checkChannel(c);
+        c.mAsyncChannel.sendMessage(GET_HANDOVER_REQUEST, 0, c.putListener(listener));
+    }
+
+
+    /**
+     * Get a handover select message for use in WFA NFC Handover transfer.
+     * @hide
+     */
+    public void getNfcHandoverSelect(Channel c, HandoverMessageListener listener) {
+        checkChannel(c);
+        c.mAsyncChannel.sendMessage(GET_HANDOVER_SELECT, 0, c.putListener(listener));
+    }
+
+    /**
+     * @hide
+     */
+    public void initiatorReportNfcHandover(Channel c, String handoverSelect,
+                                              ActionListener listener) {
+        checkChannel(c);
+        Bundle bundle = new Bundle();
+        bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverSelect);
+        c.mAsyncChannel.sendMessage(INITIATOR_REPORT_NFC_HANDOVER, 0,
+                c.putListener(listener), bundle);
+    }
+
+
+    /**
+     * @hide
+     */
+    public void responderReportNfcHandover(Channel c, String handoverRequest,
+                                              ActionListener listener) {
+        checkChannel(c);
+        Bundle bundle = new Bundle();
+        bundle.putString(EXTRA_HANDOVER_MESSAGE, handoverRequest);
+        c.mAsyncChannel.sendMessage(RESPONDER_REPORT_NFC_HANDOVER, 0,
+                c.putListener(listener), bundle);
+    }
 }