Merge "Device policy: use owner label instead of name" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 1ffa5aa..88b219c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1173,6 +1173,7 @@
     field public static final int strokeLineJoin = 16843788; // 0x101040c
     field public static final int strokeMiterLimit = 16843789; // 0x101040d
     field public static final int strokeWidth = 16843783; // 0x1010407
+    field public static final int stylusButtonPressable = 16844020; // 0x10104f4
     field public static final int submitBackground = 16843912; // 0x1010488
     field public static final int subtitle = 16843473; // 0x10102d1
     field public static final int subtitleTextAppearance = 16843823; // 0x101042f
@@ -1686,6 +1687,7 @@
     ctor public R.id();
     field public static final int accessibilityActionScrollToPosition = 16908342; // 0x1020036
     field public static final int accessibilityActionShowOnScreen = 16908341; // 0x1020035
+    field public static final int accessibilityActionStylusButtonPress = 16908344; // 0x1020038
     field public static final int addToDictionary = 16908330; // 0x102002a
     field public static final int background = 16908288; // 0x1020000
     field public static final int button1 = 16908313; // 0x1020019
@@ -4079,6 +4081,7 @@
     method public boolean isFocused();
     method public boolean isLongClickable();
     method public boolean isSelected();
+    method public boolean isStylusButtonPressable();
     field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
     field public static final int TEXT_STYLE_BOLD = 1; // 0x1
     field public static final int TEXT_STYLE_ITALIC = 2; // 0x2
@@ -4325,9 +4328,11 @@
     method public boolean getAllowReturnTransitionOverlap();
     method public final android.os.Bundle getArguments();
     method public final android.app.FragmentManager getChildFragmentManager();
+    method public android.content.Context getContext();
     method public android.transition.Transition getEnterTransition();
     method public android.transition.Transition getExitTransition();
     method public final android.app.FragmentManager getFragmentManager();
+    method public final java.lang.Object getHost();
     method public final int getId();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
@@ -4357,7 +4362,8 @@
     method public final boolean isVisible();
     method public void onActivityCreated(android.os.Bundle);
     method public void onActivityResult(int, int, android.content.Intent);
-    method public void onAttach(android.app.Activity);
+    method public void onAttach(android.content.Context);
+    method public deprecated void onAttach(android.app.Activity);
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public boolean onContextItemSelected(android.view.MenuItem);
     method public void onCreate(android.os.Bundle);
@@ -4371,7 +4377,8 @@
     method public void onDetach();
     method public void onHiddenChanged(boolean);
     method public deprecated void onInflate(android.util.AttributeSet, android.os.Bundle);
-    method public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
+    method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
+    method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
     method public void onLowMemory();
     method public boolean onOptionsItemSelected(android.view.MenuItem);
     method public void onOptionsMenuClosed(android.view.Menu);
@@ -4438,6 +4445,64 @@
     method public abstract boolean onBreadCrumbClick(android.app.FragmentManager.BackStackEntry, int);
   }
 
+  public abstract class FragmentContainer {
+    ctor public FragmentContainer();
+    method public abstract android.view.View onFindViewById(int);
+    method public abstract boolean onHasView();
+  }
+
+  public class FragmentController {
+    method public void attachHost(android.app.Fragment);
+    method public static final android.app.FragmentController createController(android.app.FragmentHostCallback<?>);
+    method public void dispatchActivityCreated();
+    method public void dispatchConfigurationChanged(android.content.res.Configuration);
+    method public boolean dispatchContextItemSelected(android.view.MenuItem);
+    method public void dispatchCreate();
+    method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method public void dispatchDestroy();
+    method public void dispatchDestroyView();
+    method public void dispatchLowMemory();
+    method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+    method public void dispatchOptionsMenuClosed(android.view.Menu);
+    method public void dispatchPause();
+    method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+    method public void dispatchResume();
+    method public void dispatchStart();
+    method public void dispatchStop();
+    method public void dispatchTrimMemory(int);
+    method public void doLoaderDestroy();
+    method public void doLoaderStart();
+    method public void doLoaderStop(boolean);
+    method public void dumpLoaders(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public boolean execPendingActions();
+    method public android.app.Fragment findFragmentByWho(java.lang.String);
+    method public android.app.FragmentManager getFragmentManager();
+    method public android.app.LoaderManager getLoaderManager();
+    method public void noteStateNotSaved();
+    method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+    method public void reportLoaderStart();
+    method public void restoreAllState(android.os.Parcelable, java.util.List<android.app.Fragment>);
+    method public void restoreLoaderNonConfig(android.util.ArrayMap<java.lang.String, android.app.LoaderManager>);
+    method public android.util.ArrayMap<java.lang.String, android.app.LoaderManager> retainLoaderNonConfig();
+    method public java.util.List<android.app.Fragment> retainNonConfig();
+    method public android.os.Parcelable saveAllState();
+  }
+
+  public abstract class FragmentHostCallback extends android.app.FragmentContainer {
+    ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+    method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public android.view.View onFindViewById(int);
+    method public abstract E onGetHost();
+    method public android.view.LayoutInflater onGetLayoutInflater();
+    method public int onGetWindowAnimations();
+    method public boolean onHasView();
+    method public boolean onHasWindowAnimations();
+    method public void onInvalidateOptionsMenu();
+    method public boolean onShouldSaveFragmentState(android.app.Fragment);
+    method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+    method public boolean onUseFragmentManagerInflaterFactory();
+  }
+
   public abstract class FragmentManager {
     ctor public FragmentManager();
     method public abstract void addOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener);
@@ -18373,6 +18438,7 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
+    method public void onPreCheck(android.net.Network);
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -30192,6 +30258,7 @@
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
     method public void registerCallback(android.telecom.Call.Callback);
+    method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, java.lang.String);
     method public void splitFromConference();
     method public void stopDtmfTone();
@@ -30499,6 +30566,7 @@
   public static abstract class InCallService.VideoCall {
     ctor public InCallService.VideoCall();
     method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback);
+    method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback, android.os.Handler);
     method public abstract void requestCallDataUsage();
     method public abstract void requestCameraCapabilities();
     method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile);
@@ -30509,7 +30577,7 @@
     method public abstract void setPauseImage(java.lang.String);
     method public abstract void setPreviewSurface(android.view.Surface);
     method public abstract void setZoom(float);
-    method public abstract void unregisterCallback();
+    method public abstract void unregisterCallback(android.telecom.InCallService.VideoCall.Callback);
   }
 
   public static abstract class InCallService.VideoCall.Callback {
@@ -30597,6 +30665,7 @@
     method public void merge();
     method public void playDtmfTone(char);
     method public final void registerCallback(android.telecom.RemoteConference.Callback);
+    method public final void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler);
     method public void separate(android.telecom.RemoteConnection);
     method public void setAudioState(android.telecom.AudioState);
     method public void stopDtmfTone();
@@ -30636,6 +30705,7 @@
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
     method public void registerCallback(android.telecom.RemoteConnection.Callback);
+    method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
     method public void reject();
     method public void setAudioState(android.telecom.AudioState);
     method public void stopDtmfTone();
@@ -34874,6 +34944,7 @@
     field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1
     field public static final int KEYBOARD_TAP = 3; // 0x3
     field public static final int LONG_PRESS = 0; // 0x0
+    field public static final int STYLUS_BUTTON_PRESS = 6; // 0x6
     field public static final int VIRTUAL_KEY = 1; // 0x1
   }
 
@@ -35606,6 +35677,7 @@
     method public final float getY(int);
     method public final float getYPrecision();
     method public final boolean isButtonPressed(int);
+    method public final boolean isStylusButtonPressed();
     method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int);
     method public static deprecated android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int);
     method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int);
@@ -36210,6 +36282,7 @@
     method public boolean isSelected();
     method public boolean isShown();
     method public boolean isSoundEffectsEnabled();
+    method public boolean isStylusButtonPressable();
     method public boolean isTextAlignmentResolved();
     method public boolean isTextDirectionResolved();
     method public boolean isVerticalFadingEdgeEnabled();
@@ -36277,6 +36350,7 @@
     method public boolean performHapticFeedback(int);
     method public boolean performHapticFeedback(int, int);
     method public boolean performLongClick();
+    method public boolean performStylusButtonPress();
     method public void playSoundEffect(int);
     method public boolean post(java.lang.Runnable);
     method public boolean postDelayed(java.lang.Runnable, long);
@@ -36380,6 +36454,7 @@
     method public void setOnKeyListener(android.view.View.OnKeyListener);
     method public void setOnLongClickListener(android.view.View.OnLongClickListener);
     method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
+    method public void setOnStylusButtonPressListener(android.view.View.OnStylusButtonPressListener);
     method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
     method public void setOnTouchListener(android.view.View.OnTouchListener);
     method public void setOutlineProvider(android.view.ViewOutlineProvider);
@@ -36408,6 +36483,7 @@
     method public void setSelected(boolean);
     method public void setSoundEffectsEnabled(boolean);
     method public void setStateListAnimator(android.animation.StateListAnimator);
+    method public void setStylusButtonPressable(boolean);
     method public void setSystemUiVisibility(int);
     method public void setTag(java.lang.Object);
     method public void setTag(int, java.lang.Object);
@@ -36655,6 +36731,10 @@
     method public abstract void onScrollChange(android.view.View, int, int, int, int);
   }
 
+  public static abstract interface View.OnStylusButtonPressListener {
+    method public abstract boolean onStylusButtonPress(android.view.View);
+  }
+
   public static abstract interface View.OnSystemUiVisibilityChangeListener {
     method public abstract void onSystemUiVisibilityChange(int);
   }
@@ -36696,6 +36776,7 @@
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
     method public abstract void setLongClickable(boolean);
     method public abstract void setSelected(boolean);
+    method public abstract void setStylusButtonPressable(boolean);
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
     method public abstract void setTextPaint(android.text.TextPaint);
@@ -37581,6 +37662,7 @@
     field public static final int TYPE_VIEW_LONG_CLICKED = 2; // 0x2
     field public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
     field public static final int TYPE_VIEW_SELECTED = 4; // 0x4
+    field public static final int TYPE_VIEW_STYLUS_BUTTON_PRESSED = 8388608; // 0x800000
     field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10
     field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
     field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072; // 0x20000
@@ -37671,6 +37753,7 @@
     method public boolean isPassword();
     method public boolean isScrollable();
     method public boolean isSelected();
+    method public boolean isStylusButtonPressable();
     method public boolean isVisibleToUser();
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View, int);
@@ -37721,6 +37804,7 @@
     method public void setSelected(boolean);
     method public void setSource(android.view.View);
     method public void setSource(android.view.View, int);
+    method public void setStylusButtonPressable(boolean);
     method public void setText(java.lang.CharSequence);
     method public void setTextSelection(int, int);
     method public void setTraversalAfter(android.view.View);
@@ -37798,6 +37882,7 @@
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_SELECTION;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SHOW_ON_SCREEN;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_STYLUS_BUTTON_PRESS;
   }
 
   public static final class AccessibilityNodeInfo.CollectionInfo {
diff --git a/api/system-current.txt b/api/system-current.txt
index 15989b3..9b7d15c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1248,6 +1248,7 @@
     field public static final int strokeLineJoin = 16843788; // 0x101040c
     field public static final int strokeMiterLimit = 16843789; // 0x101040d
     field public static final int strokeWidth = 16843783; // 0x1010407
+    field public static final int stylusButtonPressable = 16844020; // 0x10104f4
     field public static final int submitBackground = 16843912; // 0x1010488
     field public static final int subtitle = 16843473; // 0x10102d1
     field public static final int subtitleTextAppearance = 16843823; // 0x101042f
@@ -1761,6 +1762,7 @@
     ctor public R.id();
     field public static final int accessibilityActionScrollToPosition = 16908342; // 0x1020036
     field public static final int accessibilityActionShowOnScreen = 16908341; // 0x1020035
+    field public static final int accessibilityActionStylusButtonPress = 16908344; // 0x1020038
     field public static final int addToDictionary = 16908330; // 0x102002a
     field public static final int background = 16908288; // 0x1020000
     field public static final int button1 = 16908313; // 0x1020019
@@ -4169,6 +4171,7 @@
     method public boolean isFocused();
     method public boolean isLongClickable();
     method public boolean isSelected();
+    method public boolean isStylusButtonPressable();
     field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
     field public static final int TEXT_STYLE_BOLD = 1; // 0x1
     field public static final int TEXT_STYLE_ITALIC = 2; // 0x2
@@ -4415,9 +4418,11 @@
     method public boolean getAllowReturnTransitionOverlap();
     method public final android.os.Bundle getArguments();
     method public final android.app.FragmentManager getChildFragmentManager();
+    method public android.content.Context getContext();
     method public android.transition.Transition getEnterTransition();
     method public android.transition.Transition getExitTransition();
     method public final android.app.FragmentManager getFragmentManager();
+    method public final java.lang.Object getHost();
     method public final int getId();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
@@ -4447,7 +4452,8 @@
     method public final boolean isVisible();
     method public void onActivityCreated(android.os.Bundle);
     method public void onActivityResult(int, int, android.content.Intent);
-    method public void onAttach(android.app.Activity);
+    method public void onAttach(android.content.Context);
+    method public deprecated void onAttach(android.app.Activity);
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public boolean onContextItemSelected(android.view.MenuItem);
     method public void onCreate(android.os.Bundle);
@@ -4461,7 +4467,8 @@
     method public void onDetach();
     method public void onHiddenChanged(boolean);
     method public deprecated void onInflate(android.util.AttributeSet, android.os.Bundle);
-    method public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
+    method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
+    method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
     method public void onLowMemory();
     method public boolean onOptionsItemSelected(android.view.MenuItem);
     method public void onOptionsMenuClosed(android.view.Menu);
@@ -4528,6 +4535,64 @@
     method public abstract boolean onBreadCrumbClick(android.app.FragmentManager.BackStackEntry, int);
   }
 
+  public abstract class FragmentContainer {
+    ctor public FragmentContainer();
+    method public abstract android.view.View onFindViewById(int);
+    method public abstract boolean onHasView();
+  }
+
+  public class FragmentController {
+    method public void attachHost(android.app.Fragment);
+    method public static final android.app.FragmentController createController(android.app.FragmentHostCallback<?>);
+    method public void dispatchActivityCreated();
+    method public void dispatchConfigurationChanged(android.content.res.Configuration);
+    method public boolean dispatchContextItemSelected(android.view.MenuItem);
+    method public void dispatchCreate();
+    method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method public void dispatchDestroy();
+    method public void dispatchDestroyView();
+    method public void dispatchLowMemory();
+    method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+    method public void dispatchOptionsMenuClosed(android.view.Menu);
+    method public void dispatchPause();
+    method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+    method public void dispatchResume();
+    method public void dispatchStart();
+    method public void dispatchStop();
+    method public void dispatchTrimMemory(int);
+    method public void doLoaderDestroy();
+    method public void doLoaderStart();
+    method public void doLoaderStop(boolean);
+    method public void dumpLoaders(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public boolean execPendingActions();
+    method public android.app.Fragment findFragmentByWho(java.lang.String);
+    method public android.app.FragmentManager getFragmentManager();
+    method public android.app.LoaderManager getLoaderManager();
+    method public void noteStateNotSaved();
+    method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+    method public void reportLoaderStart();
+    method public void restoreAllState(android.os.Parcelable, java.util.List<android.app.Fragment>);
+    method public void restoreLoaderNonConfig(android.util.ArrayMap<java.lang.String, android.app.LoaderManager>);
+    method public android.util.ArrayMap<java.lang.String, android.app.LoaderManager> retainLoaderNonConfig();
+    method public java.util.List<android.app.Fragment> retainNonConfig();
+    method public android.os.Parcelable saveAllState();
+  }
+
+  public abstract class FragmentHostCallback extends android.app.FragmentContainer {
+    ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+    method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public android.view.View onFindViewById(int);
+    method public abstract E onGetHost();
+    method public android.view.LayoutInflater onGetLayoutInflater();
+    method public int onGetWindowAnimations();
+    method public boolean onHasView();
+    method public boolean onHasWindowAnimations();
+    method public void onInvalidateOptionsMenu();
+    method public boolean onShouldSaveFragmentState(android.app.Fragment);
+    method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+    method public boolean onUseFragmentManagerInflaterFactory();
+  }
+
   public abstract class FragmentManager {
     ctor public FragmentManager();
     method public abstract void addOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener);
@@ -19841,6 +19906,7 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
+    method public void onPreCheck(android.net.Network);
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -32306,6 +32372,7 @@
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
     method public void registerCallback(android.telecom.Call.Callback);
+    method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, java.lang.String);
     method public deprecated void removeListener(android.telecom.Call.Listener);
     method public void splitFromConference();
@@ -32622,6 +32689,7 @@
   public static abstract class InCallService.VideoCall {
     ctor public InCallService.VideoCall();
     method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback);
+    method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback, android.os.Handler);
     method public abstract void requestCallDataUsage();
     method public abstract void requestCameraCapabilities();
     method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile);
@@ -32632,7 +32700,7 @@
     method public abstract void setPauseImage(java.lang.String);
     method public abstract void setPreviewSurface(android.view.Surface);
     method public abstract void setZoom(float);
-    method public abstract void unregisterCallback();
+    method public abstract void unregisterCallback(android.telecom.InCallService.VideoCall.Callback);
   }
 
   public static abstract class InCallService.VideoCall.Callback {
@@ -32740,6 +32808,7 @@
     method public void merge();
     method public void playDtmfTone(char);
     method public final void registerCallback(android.telecom.RemoteConference.Callback);
+    method public final void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler);
     method public void separate(android.telecom.RemoteConnection);
     method public void setAudioState(android.telecom.AudioState);
     method public void stopDtmfTone();
@@ -32779,6 +32848,7 @@
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
     method public void registerCallback(android.telecom.RemoteConnection.Callback);
+    method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
     method public void reject();
     method public void setAudioState(android.telecom.AudioState);
     method public void stopDtmfTone();
@@ -37084,6 +37154,7 @@
     field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1
     field public static final int KEYBOARD_TAP = 3; // 0x3
     field public static final int LONG_PRESS = 0; // 0x0
+    field public static final int STYLUS_BUTTON_PRESS = 6; // 0x6
     field public static final int VIRTUAL_KEY = 1; // 0x1
   }
 
@@ -37816,6 +37887,7 @@
     method public final float getY(int);
     method public final float getYPrecision();
     method public final boolean isButtonPressed(int);
+    method public final boolean isStylusButtonPressed();
     method public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int);
     method public static deprecated android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent.PointerCoords[], int, float, float, int, int, int, int);
     method public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int);
@@ -38420,6 +38492,7 @@
     method public boolean isSelected();
     method public boolean isShown();
     method public boolean isSoundEffectsEnabled();
+    method public boolean isStylusButtonPressable();
     method public boolean isTextAlignmentResolved();
     method public boolean isTextDirectionResolved();
     method public boolean isVerticalFadingEdgeEnabled();
@@ -38487,6 +38560,7 @@
     method public boolean performHapticFeedback(int);
     method public boolean performHapticFeedback(int, int);
     method public boolean performLongClick();
+    method public boolean performStylusButtonPress();
     method public void playSoundEffect(int);
     method public boolean post(java.lang.Runnable);
     method public boolean postDelayed(java.lang.Runnable, long);
@@ -38590,6 +38664,7 @@
     method public void setOnKeyListener(android.view.View.OnKeyListener);
     method public void setOnLongClickListener(android.view.View.OnLongClickListener);
     method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
+    method public void setOnStylusButtonPressListener(android.view.View.OnStylusButtonPressListener);
     method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
     method public void setOnTouchListener(android.view.View.OnTouchListener);
     method public void setOutlineProvider(android.view.ViewOutlineProvider);
@@ -38618,6 +38693,7 @@
     method public void setSelected(boolean);
     method public void setSoundEffectsEnabled(boolean);
     method public void setStateListAnimator(android.animation.StateListAnimator);
+    method public void setStylusButtonPressable(boolean);
     method public void setSystemUiVisibility(int);
     method public void setTag(java.lang.Object);
     method public void setTag(int, java.lang.Object);
@@ -38865,6 +38941,10 @@
     method public abstract void onScrollChange(android.view.View, int, int, int, int);
   }
 
+  public static abstract interface View.OnStylusButtonPressListener {
+    method public abstract boolean onStylusButtonPress(android.view.View);
+  }
+
   public static abstract interface View.OnSystemUiVisibilityChangeListener {
     method public abstract void onSystemUiVisibilityChange(int);
   }
@@ -38906,6 +38986,7 @@
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
     method public abstract void setLongClickable(boolean);
     method public abstract void setSelected(boolean);
+    method public abstract void setStylusButtonPressable(boolean);
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
     method public abstract void setTextPaint(android.text.TextPaint);
@@ -39794,6 +39875,7 @@
     field public static final int TYPE_VIEW_LONG_CLICKED = 2; // 0x2
     field public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
     field public static final int TYPE_VIEW_SELECTED = 4; // 0x4
+    field public static final int TYPE_VIEW_STYLUS_BUTTON_PRESSED = 8388608; // 0x800000
     field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10
     field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
     field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072; // 0x20000
@@ -39884,6 +39966,7 @@
     method public boolean isPassword();
     method public boolean isScrollable();
     method public boolean isSelected();
+    method public boolean isStylusButtonPressable();
     method public boolean isVisibleToUser();
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View, int);
@@ -39934,6 +40017,7 @@
     method public void setSelected(boolean);
     method public void setSource(android.view.View);
     method public void setSource(android.view.View, int);
+    method public void setStylusButtonPressable(boolean);
     method public void setText(java.lang.CharSequence);
     method public void setTextSelection(int, int);
     method public void setTraversalAfter(android.view.View);
@@ -40011,6 +40095,7 @@
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_SELECTION;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SHOW_ON_SCREEN;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_STYLUS_BUTTON_PRESS;
   }
 
   public static final class AccessibilityNodeInfo.CollectionInfo {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 69cba78..e79e20c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -108,6 +108,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 
 /**
  * An activity is a single, focused thing that the user can do.  Almost all
@@ -706,8 +707,6 @@
     /*package*/ ActivityThread mMainThread;
     Activity mParent;
     boolean mCalled;
-    boolean mCheckedForLoaderManager;
-    boolean mLoadersStarted;
     /*package*/ boolean mResumed;
     private boolean mStopped;
     boolean mFinished;
@@ -726,8 +725,8 @@
     static final class NonConfigurationInstances {
         Object activity;
         HashMap<String, Object> children;
-        ArrayList<Fragment> fragments;
-        ArrayMap<String, LoaderManagerImpl> loaders;
+        List<Fragment> fragments;
+        ArrayMap<String, LoaderManager> loaders;
         VoiceInteractor voiceInteractor;
     }
     /* package */ NonConfigurationInstances mLastNonConfigurationInstances;
@@ -747,26 +746,13 @@
     private CharSequence mTitle;
     private int mTitleColor = 0;
 
-    final FragmentManagerImpl mFragments = new FragmentManagerImpl();
-    final FragmentContainer mContainer = new FragmentContainer() {
-        @Override
-        @Nullable
-        public View findViewById(int id) {
-            return Activity.this.findViewById(id);
-        }
-        @Override
-        public boolean hasView() {
-            Window window = Activity.this.getWindow();
-            return (window != null && window.peekDecorView() != null);
-        }
-    };
+    // we must have a handler before the FragmentController is constructed
+    final Handler mHandler = new Handler();
+    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
 
     // Most recent call to requestVisibleBehind().
     boolean mVisibleBehind;
 
-    ArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;
-    LoaderManagerImpl mLoaderManager;
-
     private static final class ManagedCursor {
         ManagedCursor(Cursor cursor) {
             mCursor = cursor;
@@ -802,7 +788,6 @@
     private final Object mInstanceTracker = StrictMode.trackActivity(this);
 
     private Thread mUiThread;
-    final Handler mHandler = new Handler();
 
     ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
     SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
@@ -863,28 +848,7 @@
      * Return the LoaderManager for this activity, creating it if needed.
      */
     public LoaderManager getLoaderManager() {
-        if (mLoaderManager != null) {
-            return mLoaderManager;
-        }
-        mCheckedForLoaderManager = true;
-        mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);
-        return mLoaderManager;
-    }
-
-    LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
-        if (mAllLoaderManagers == null) {
-            mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>();
-        }
-        LoaderManagerImpl lm = mAllLoaderManagers.get(who);
-        if (lm == null) {
-            if (create) {
-                lm = new LoaderManagerImpl(who, this, started);
-                mAllLoaderManagers.put(who, lm);
-            }
-        } else {
-            lm.updateActivity(this);
-        }
-        return lm;
+        return mFragments.getLoaderManager();
     }
 
     /**
@@ -931,7 +895,7 @@
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
         if (mLastNonConfigurationInstances != null) {
-            mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
+            mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
         }
         if (mActivityInfo.parentActivityName != null) {
             if (mActionBar == null) {
@@ -1172,15 +1136,7 @@
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
         mCalled = true;
 
-        if (!mLoadersStarted) {
-            mLoadersStarted = true;
-            if (mLoaderManager != null) {
-                mLoaderManager.doStart();
-            } else if (!mCheckedForLoaderManager) {
-                mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
-            }
-            mCheckedForLoaderManager = true;
-        }
+        mFragments.doLoaderStart();
 
         getApplication().dispatchActivityStarted(this);
     }
@@ -1873,27 +1829,9 @@
     NonConfigurationInstances retainNonConfigurationInstances() {
         Object activity = onRetainNonConfigurationInstance();
         HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
-        ArrayList<Fragment> fragments = mFragments.retainNonConfig();
-        boolean retainLoaders = false;
-        if (mAllLoaderManagers != null) {
-            // prune out any loader managers that were already stopped and so
-            // have nothing useful to retain.
-            final int N = mAllLoaderManagers.size();
-            LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
-            for (int i=N-1; i>=0; i--) {
-                loaders[i] = mAllLoaderManagers.valueAt(i);
-            }
-            for (int i=0; i<N; i++) {
-                LoaderManagerImpl lm = loaders[i];
-                if (lm.mRetaining) {
-                    retainLoaders = true;
-                } else {
-                    lm.doDestroy();
-                    mAllLoaderManagers.remove(lm.mWho);
-                }
-            }
-        }
-        if (activity == null && children == null && fragments == null && !retainLoaders
+        List<Fragment> fragments = mFragments.retainNonConfig();
+        ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
+        if (activity == null && children == null && fragments == null && loaders == null
                 && mVoiceInteractor == null) {
             return null;
         }
@@ -1902,7 +1840,7 @@
         nci.activity = activity;
         nci.children = children;
         nci.fragments = fragments;
-        nci.loaders = mAllLoaderManagers;
+        nci.loaders = loaders;
         nci.voiceInteractor = mVoiceInteractor;
         return nci;
     }
@@ -1924,18 +1862,7 @@
      * with this activity.
      */
     public FragmentManager getFragmentManager() {
-        return mFragments;
-    }
-
-    void invalidateFragment(String who) {
-        //Log.v(TAG, "invalidateFragmentIndex: index=" + index);
-        if (mAllLoaderManagers != null) {
-            LoaderManagerImpl lm = mAllLoaderManagers.get(who);
-            if (lm != null && !lm.mRetaining) {
-                lm.doDestroy();
-                mAllLoaderManagers.remove(who);
-            }
-        }
+        return mFragments.getFragmentManager();
     }
 
     /**
@@ -2518,7 +2445,7 @@
             return;
         }
 
-        if (!mFragments.popBackStackImmediate()) {
+        if (!mFragments.getFragmentManager().popBackStackImmediate()) {
             finishAfterTransition();
         }
     }
@@ -5518,21 +5445,13 @@
                 writer.print(mResumed); writer.print(" mStopped=");
                 writer.print(mStopped); writer.print(" mFinished=");
                 writer.println(mFinished);
-        writer.print(innerPrefix); writer.print("mLoadersStarted=");
-                writer.println(mLoadersStarted);
         writer.print(innerPrefix); writer.print("mChangingConfigurations=");
                 writer.println(mChangingConfigurations);
         writer.print(innerPrefix); writer.print("mCurrentConfig=");
                 writer.println(mCurrentConfig);
 
-        if (mLoaderManager != null) {
-            writer.print(prefix); writer.print("Loader Manager ");
-                    writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
-                    writer.println(":");
-            mLoaderManager.dump(prefix + "  ", fd, writer, args);
-        }
-
-        mFragments.dump(prefix, fd, writer, args);
+        mFragments.dumpLoaders(innerPrefix, fd, writer, args);
+        mFragments.getFragmentManager().dump(innerPrefix, fd, writer, args);
 
         if (getWindow() != null &&
                 getWindow().peekDecorView() != null &&
@@ -6128,7 +6047,7 @@
             Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
         attachBaseContext(context);
 
-        mFragments.attachActivity(this, mContainer, null);
+        mFragments.attachHost(null /*parent*/);
 
         mWindow = new PhoneWindow(this);
         mWindow.setCallback(this);
@@ -6211,18 +6130,7 @@
                 " did not call through to super.onStart()");
         }
         mFragments.dispatchStart();
-        if (mAllLoaderManagers != null) {
-            final int N = mAllLoaderManagers.size();
-            LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
-            for (int i=N-1; i>=0; i--) {
-                loaders[i] = mAllLoaderManagers.valueAt(i);
-            }
-            for (int i=0; i<N; i++) {
-                LoaderManagerImpl lm = loaders[i];
-                lm.finishRetain();
-                lm.doReportStart();
-            }
-        }
+        mFragments.reportLoaderStart();
         mActivityTransitionState.enterReady(this);
     }
 
@@ -6328,16 +6236,7 @@
 
     final void performStop() {
         mDoReportFullyDrawn = false;
-        if (mLoadersStarted) {
-            mLoadersStarted = false;
-            if (mLoaderManager != null) {
-                if (!mChangingConfigurations) {
-                    mLoaderManager.doStop();
-                } else {
-                    mLoaderManager.doRetain();
-                }
-            }
-        }
+        mFragments.doLoaderStop(mChangingConfigurations /*retain*/);
 
         if (!mStopped) {
             if (mWindow != null) {
@@ -6379,9 +6278,7 @@
         mWindow.destroy();
         mFragments.dispatchDestroy();
         onDestroy();
-        if (mLoaderManager != null) {
-            mLoaderManager.doDestroy();
-        }
+        mFragments.doLoaderDestroy();
         if (mVoiceInteractor != null) {
             mVoiceInteractor.detachActivity();
         }
@@ -6541,4 +6438,74 @@
         return intent != null
                 && PackageManager.ACTION_REQUEST_PERMISSIONS.equals(intent.getAction());
     }
+
+    class HostCallbacks extends FragmentHostCallback<Activity> {
+        public HostCallbacks() {
+            super(Activity.this /*activity*/);
+        }
+
+        @Override
+        public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+            Activity.this.dump(prefix, fd, writer, args);
+        }
+
+        @Override
+        public boolean onShouldSaveFragmentState(Fragment fragment) {
+            return !isFinishing();
+        }
+
+        @Override
+        public LayoutInflater onGetLayoutInflater() {
+            final LayoutInflater result = Activity.this.getLayoutInflater();
+            if (onUseFragmentManagerInflaterFactory()) {
+                return result.cloneInContext(Activity.this);
+            }
+            return result;
+        }
+
+        @Override
+        public boolean onUseFragmentManagerInflaterFactory() {
+            // Newer platform versions use the child fragment manager's LayoutInflaterFactory.
+            return getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
+        }
+
+        @Override
+        public Activity onGetHost() {
+            return Activity.this;
+        }
+
+        @Override
+        public void onInvalidateOptionsMenu() {
+            Activity.this.invalidateOptionsMenu();
+        }
+
+        @Override
+        public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
+                Bundle options) {
+            Activity.this.startActivityFromFragment(fragment, intent, requestCode, options);
+        }
+
+        @Override
+        public boolean onHasWindowAnimations() {
+            return getWindow() != null;
+        }
+
+        @Override
+        public int onGetWindowAnimations() {
+            final Window w = getWindow();
+            return (w == null) ? 0 : w.getAttributes().windowAnimations;
+        }
+
+        @Nullable
+        @Override
+        public View onFindViewById(int id) {
+            return Activity.this.findViewById(id);
+        }
+
+        @Override
+        public boolean onHasView() {
+            final Window w = getWindow();
+            return (w != null && w.peekDecorView() != null);
+        }
+    }
 }
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 9d1d312..b0fda9c 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -26,6 +26,10 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.text.TextUtils;
+import libcore.util.ZoneInfoDB;
+
+import java.io.IOException;
 
 /**
  * This class provides access to the system alarm services.  These allow you
@@ -151,6 +155,7 @@
 
     private final IAlarmManager mService;
     private final boolean mAlwaysExact;
+    private final int mTargetSdkVersion;
 
 
     /**
@@ -159,8 +164,8 @@
     AlarmManager(IAlarmManager service, Context ctx) {
         mService = service;
 
-        final int sdkVersion = ctx.getApplicationInfo().targetSdkVersion;
-        mAlwaysExact = (sdkVersion < Build.VERSION_CODES.KITKAT);
+        mTargetSdkVersion = ctx.getApplicationInfo().targetSdkVersion;
+        mAlwaysExact = (mTargetSdkVersion < Build.VERSION_CODES.KITKAT);
     }
 
     private long legacyExactLength() {
@@ -585,12 +590,38 @@
     }
 
     /**
-     * Set the system default time zone.
-     * Requires the permission android.permission.SET_TIME_ZONE.
+     * Sets the system's persistent default time zone. This is the time zone for all apps, even
+     * after a reboot. Use {@link java.util.TimeZone#setDefault} if you just want to change the
+     * time zone within your app, and even then prefer to pass an explicit
+     * {@link java.util.TimeZone} to APIs that require it rather than changing the time zone for
+     * all threads.
      *
-     * @param timeZone in the format understood by {@link java.util.TimeZone}
+     * <p> On android M and above, it is an error to pass in a non-Olson timezone to this
+     * function. Note that this is a bad idea on all Android releases because POSIX and
+     * the {@code TimeZone} class have opposite interpretations of {@code '+'} and {@code '-'}
+     * in the same non-Olson ID.
+     *
+     * @param timeZone one of the Olson ids from the list returned by
+     *     {@link java.util.TimeZone#getAvailableIDs}
      */
     public void setTimeZone(String timeZone) {
+        if (TextUtils.isEmpty(timeZone)) {
+            return;
+        }
+
+        // Reject this timezone if it isn't an Olson zone we recognize.
+        if (mTargetSdkVersion >= Build.VERSION_CODES.MNC) {
+            boolean hasTimeZone = false;
+            try {
+                hasTimeZone = ZoneInfoDB.getInstance().hasTimeZone(timeZone);
+            } catch (IOException ignored) {
+            }
+
+            if (!hasTimeZone) {
+                throw new IllegalArgumentException("Timezone: " + timeZone + " is not an Olson ID");
+            }
+        }
+
         try {
             mService.setTimeZone(timeZone);
         } catch (RemoteException ex) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1127436..8a3c9c8 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -217,8 +217,14 @@
     public static final int OP_READ_PHONE_STATE = 51;
     /** @hide Add voicemail messages to the voicemail content provider. */
     public static final int OP_ADD_VOICEMAIL = 52;
+    /** @hide Access APIs for SIP calling over VOIP or WiFi. */
+    public static final int OP_USE_SIP = 53;
+    /** @hide Intercept outgoing calls. */
+    public static final int OP_PROCESS_OUTGOING_CALLS = 54;
+    /** @hide User the fingerprint API. */
+    public static final int OP_USE_FINGERPRINT = 55;
     /** @hide */
-    public static final int _NUM_OP = 53;
+    public static final int _NUM_OP = 56;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -351,7 +357,10 @@
             OP_ASSIST_STRUCTURE,
             OP_ASSIST_SCREENSHOT,
             OP_READ_PHONE_STATE,
-            OP_ADD_VOICEMAIL
+            OP_ADD_VOICEMAIL,
+            OP_USE_SIP,
+            OP_PROCESS_OUTGOING_CALLS,
+            OP_USE_FINGERPRINT
     };
 
     /**
@@ -411,6 +420,9 @@
             null,
             null,
             null,
+            null,
+            null,
+            null,
             null
     };
 
@@ -471,7 +483,10 @@
             "ASSIST_STRUCTURE",
             "ASSIST_SCREENSHOT",
             "OP_READ_PHONE_STATE",
-            "ADD_VOICEMAIL"
+            "ADD_VOICEMAIL",
+            "USE_SIP",
+            "PROCESS_OUTGOING_CALLS",
+            "USE_FINGERPRINT"
     };
 
     /**
@@ -531,7 +546,10 @@
             null, // no permission for receiving assist structure
             null, // no permission for receiving assist screenshot
             Manifest.permission.READ_PHONE_STATE,
-            Manifest.permission.ADD_VOICEMAIL
+            Manifest.permission.ADD_VOICEMAIL,
+            Manifest.permission.USE_SIP,
+            Manifest.permission.PROCESS_OUTGOING_CALLS,
+            Manifest.permission.USE_FINGERPRINT
     };
 
     /**
@@ -592,7 +610,10 @@
             null, // ASSIST_STRUCTURE
             null, // ASSIST_SCREENSHOT
             null, // READ_PHONE_STATE
-            null // ADD_VOICEMAIL
+            null, // ADD_VOICEMAIL
+            null, // USE_SIP
+            null, // PROCESS_OUTGOING_CALLS
+            null  // USE_FINGERPRINT
     };
 
     /**
@@ -652,7 +673,10 @@
             false, //ASSIST_STRUCTURE
             false, //ASSIST_SCREENSHOT
             false, //READ_PHONE_STATE
-            false  //ADD_VOICEMAIL
+            false, //ADD_VOICEMAIL
+            false, // USE_SIP
+            false, // PROCESS_OUTGOING_CALLS
+            false  // USE_FINGERPRINT
     };
 
     /**
@@ -711,6 +735,9 @@
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
+            AppOpsManager.MODE_ALLOWED,
+            AppOpsManager.MODE_ALLOWED,
+            AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED
     };
 
@@ -774,6 +801,9 @@
             false,
             false,
             false,
+            false,
+            false,
+            false,
             false
     };
 
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index 9946d79..3abbb5b 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -224,6 +224,7 @@
         static final int FLAGS_CHECKED = 0x00000200;
         static final int FLAGS_CLICKABLE = 0x00004000;
         static final int FLAGS_LONG_CLICKABLE = 0x00200000;
+        static final int FLAGS_STYLUS_BUTTON_PRESSABLE = 0x00400000;
 
         int mFlags;
 
@@ -401,6 +402,10 @@
             return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
         }
 
+        public boolean isStylusButtonPressable() {
+            return (mFlags&ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE) != 0;
+        }
+
         public String getClassName() {
             return mClassName;
         }
@@ -513,6 +518,12 @@
         }
 
         @Override
+        public void setStylusButtonPressable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE)
+                    | (state ? ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE : 0);
+        }
+
+        @Override
         public void setFocusable(boolean state) {
             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE)
                     | (state ? ViewNode.FLAGS_FOCUSABLE : 0);
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 8fb048b..49644a7 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -416,14 +416,14 @@
 
     public CharSequence getBreadCrumbTitle() {
         if (mBreadCrumbTitleRes != 0) {
-            return mManager.mActivity.getText(mBreadCrumbTitleRes);
+            return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
         }
         return mBreadCrumbTitleText;
     }
 
     public CharSequence getBreadCrumbShortTitle() {
         if (mBreadCrumbShortTitleRes != 0) {
-            return mManager.mActivity.getText(mBreadCrumbShortTitleRes);
+            return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
         }
         return mBreadCrumbShortTitleText;
     }
@@ -868,7 +868,7 @@
      */
     private void calculateFragments(SparseArray<Fragment> firstOutFragments,
             SparseArray<Fragment> lastInFragments) {
-        if (!mManager.mContainer.hasView()) {
+        if (!mManager.mContainer.onHasView()) {
             return; // nothing to see, so no transitions
         }
         Op op = mHead;
@@ -926,7 +926,7 @@
      */
     public void calculateBackFragments(SparseArray<Fragment> firstOutFragments,
             SparseArray<Fragment> lastInFragments) {
-        if (!mManager.mContainer.hasView()) {
+        if (!mManager.mContainer.onHasView()) {
             return; // nothing to see, so no transitions
         }
         Op op = mHead;
@@ -1002,7 +1002,7 @@
         // Adding a non-existent target view makes sure that the transitions don't target
         // any views by default. They'll only target the views we tell add. If we don't
         // add any, then no views will be targeted.
-        state.nonExistentView = new View(mManager.mActivity);
+        state.nonExistentView = new View(mManager.mHost.getContext());
 
         // Go over all leaving fragments.
         for (int i = 0; i < firstOutFragments.size(); i++) {
@@ -1275,7 +1275,7 @@
      */
     private void configureTransitions(int containerId, TransitionState state, boolean isBack,
             SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) {
-        ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId);
+        ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.onFindViewById(containerId);
         if (sceneRoot != null) {
             Fragment inFragment = lastInFragments.get(containerId);
             Fragment outFragment = firstOutFragments.get(containerId);
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index bde5a61..2fb8cc2 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -410,7 +410,7 @@
             return (LayoutInflater)mDialog.getContext().getSystemService(
                     Context.LAYOUT_INFLATER_SERVICE);
         }
-        return (LayoutInflater)mActivity.getSystemService(
+        return (LayoutInflater) mHost.getContext().getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
     }
     
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 4fdae7f..91d810e 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -26,7 +26,6 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -94,19 +93,20 @@
         mSavedFragmentState = in.readBundle();
     }
 
-    public Fragment instantiate(Activity activity, Fragment parent) {
+    public Fragment instantiate(FragmentHostCallback host, Fragment parent) {
         if (mInstance != null) {
             return mInstance;
         }
 
+        final Context context = host.getContext();
         if (mArguments != null) {
-            mArguments.setClassLoader(activity.getClassLoader());
+            mArguments.setClassLoader(context.getClassLoader());
         }
 
-        mInstance = Fragment.instantiate(activity, mClassName, mArguments);
+        mInstance = Fragment.instantiate(context, mClassName, mArguments);
 
         if (mSavedFragmentState != null) {
-            mSavedFragmentState.setClassLoader(activity.getClassLoader());
+            mSavedFragmentState.setClassLoader(context.getClassLoader());
             mInstance.mSavedFragmentState = mSavedFragmentState;
         }
         mInstance.setIndex(mIndex, parent);
@@ -117,7 +117,7 @@
         mInstance.mTag = mTag;
         mInstance.mRetainInstance = mRetainInstance;
         mInstance.mDetached = mDetached;
-        mInstance.mFragmentManager = activity.mFragments;
+        mInstance.mFragmentManager = host.mFragmentManager;
         if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
                 "Instantiated fragment " + mInstance);
 
@@ -425,7 +425,7 @@
     FragmentManagerImpl mFragmentManager;
 
     // Activity this fragment is attached to.
-    Activity mActivity;
+    FragmentHostCallback mHost;
 
     // Private fragment manager for child fragments inside of this one.
     FragmentManagerImpl mChildFragmentManager;
@@ -775,20 +775,36 @@
     }
 
     /**
+     * Return the {@link Context} this fragment is currently associated with.
+     */
+    public Context getContext() {
+        return mHost == null ? null : mHost.getContext();
+    }
+
+    /**
      * Return the Activity this fragment is currently associated with.
      */
     final public Activity getActivity() {
-        return mActivity;
+        return mHost == null ? null : mHost.getActivity();
+    }
+
+    /**
+     * Return the host object of this fragment. May return {@code null} if the fragment
+     * isn't currently being hosted.
+     */
+    @Nullable
+    final public Object getHost() {
+        return mHost == null ? null : mHost.onGetHost();
     }
 
     /**
      * Return <code>getActivity().getResources()</code>.
      */
     final public Resources getResources() {
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
-        return mActivity.getResources();
+        return mHost.getContext().getResources();
     }
 
     /**
@@ -870,7 +886,7 @@
      * Return true if the fragment is currently added to its activity.
      */
     final public boolean isAdded() {
-        return mActivity != null && mAdded;
+        return mHost != null && mAdded;
     }
 
     /**
@@ -1037,11 +1053,11 @@
         if (mLoaderManager != null) {
             return mLoaderManager;
         }
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
         mCheckedForLoaderManager = true;
-        mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true);
+        mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, true);
         return mLoaderManager;
     }
 
@@ -1065,15 +1081,15 @@
      * Context.startActivity(Intent, Bundle)} for more details.
      */
     public void startActivity(Intent intent, Bundle options) {
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
         if (options != null) {
-            mActivity.startActivityFromFragment(this, intent, -1, options);
+            mHost.onStartActivityFromFragment(this, intent, -1, options);
         } else {
             // Note we want to go through this call for compatibility with
             // applications that may have overridden the method.
-            mActivity.startActivityFromFragment(this, intent, -1);
+            mHost.onStartActivityFromFragment(this, intent, -1, null /*options*/);
         }
     }
 
@@ -1090,10 +1106,10 @@
      * containing Activity.
      */
     public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
-        mActivity.startActivityFromFragment(this, intent, requestCode, options);
+        mHost.onStartActivityFromFragment(this, intent, requestCode, options);
     }
 
     /**
@@ -1181,11 +1197,12 @@
      * @see android.content.Context#checkSelfPermission(String)
      */
     public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
-        Intent intent = mActivity.getPackageManager().buildRequestPermissionsIntent(permissions);
-        mActivity.startActivityFromFragment(this, intent, requestCode, null);
+        Intent intent =
+                mHost.getContext().getPackageManager().buildRequestPermissionsIntent(permissions);
+        mHost.onStartActivityFromFragment(this, intent, requestCode, null);
     }
 
     /**
@@ -1211,19 +1228,16 @@
      * inflation.  Maybe this should become a public API. Note sure.
      */
     public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
-        // Newer platform versions use the child fragment manager's LayoutInflaterFactory.
-        if (mActivity.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
-            LayoutInflater result = mActivity.getLayoutInflater().cloneInContext(mActivity);
+        final LayoutInflater result = mHost.onGetLayoutInflater();
+        if (mHost.onUseFragmentManagerInflaterFactory()) {
             getChildFragmentManager(); // Init if needed; use raw implementation below.
             result.setPrivateFactory(mChildFragmentManager.getLayoutInflaterFactory());
-            return result;
-        } else {
-            return mActivity.getLayoutInflater();
         }
+        return result;
     }
 
     /**
-     * @deprecated Use {@link #onInflate(Activity, AttributeSet, Bundle)} instead.
+     * @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead.
      */
     @Deprecated
     public void onInflate(AttributeSet attrs, Bundle savedInstanceState) {
@@ -1266,29 +1280,29 @@
      * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java
      *      create}
      *
-     * @param activity The Activity that is inflating this fragment.
+     * @param context The Context that is inflating this fragment.
      * @param attrs The attributes at the tag where the fragment is
      * being created.
      * @param savedInstanceState If the fragment is being re-created from
      * a previous saved state, this is the state.
      */
-    public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
+    public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
         onInflate(attrs, savedInstanceState);
         mCalled = true;
 
-        TypedArray a = activity.obtainStyledAttributes(attrs,
+        TypedArray a = context.obtainStyledAttributes(attrs,
                 com.android.internal.R.styleable.Fragment);
-        mEnterTransition = loadTransition(activity, a, mEnterTransition, null,
+        mEnterTransition = loadTransition(context, a, mEnterTransition, null,
                 com.android.internal.R.styleable.Fragment_fragmentEnterTransition);
-        mReturnTransition = loadTransition(activity, a, mReturnTransition, USE_DEFAULT_TRANSITION,
+        mReturnTransition = loadTransition(context, a, mReturnTransition, USE_DEFAULT_TRANSITION,
                 com.android.internal.R.styleable.Fragment_fragmentReturnTransition);
-        mExitTransition = loadTransition(activity, a, mExitTransition, null,
+        mExitTransition = loadTransition(context, a, mExitTransition, null,
                 com.android.internal.R.styleable.Fragment_fragmentExitTransition);
-        mReenterTransition = loadTransition(activity, a, mReenterTransition, USE_DEFAULT_TRANSITION,
+        mReenterTransition = loadTransition(context, a, mReenterTransition, USE_DEFAULT_TRANSITION,
                 com.android.internal.R.styleable.Fragment_fragmentReenterTransition);
-        mSharedElementEnterTransition = loadTransition(activity, a, mSharedElementEnterTransition,
+        mSharedElementEnterTransition = loadTransition(context, a, mSharedElementEnterTransition,
                 null, com.android.internal.R.styleable.Fragment_fragmentSharedElementEnterTransition);
-        mSharedElementReturnTransition = loadTransition(activity, a, mSharedElementReturnTransition,
+        mSharedElementReturnTransition = loadTransition(context, a, mSharedElementReturnTransition,
                 USE_DEFAULT_TRANSITION,
                 com.android.internal.R.styleable.Fragment_fragmentSharedElementReturnTransition);
         if (mAllowEnterTransitionOverlap == null) {
@@ -1303,9 +1317,30 @@
     }
 
     /**
-     * Called when a fragment is first attached to its activity.
+     * @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead.
+     */
+    @Deprecated
+    public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
+        mCalled = true;
+    }
+
+    /**
+     * Called when a fragment is first attached to its context.
      * {@link #onCreate(Bundle)} will be called after this.
      */
+    public void onAttach(Context context) {
+        mCalled = true;
+        final Activity hostActivity = mHost == null ? null : mHost.getActivity();
+        if (hostActivity != null) {
+            mCalled = false;
+            onAttach(hostActivity);
+        }
+    }
+
+    /**
+     * @deprecated Use {@link #onAttach(Context)} instead.
+     */
+    @Deprecated
     public void onAttach(Activity activity) {
         mCalled = true;
     }
@@ -1428,7 +1463,7 @@
             mLoadersStarted = true;
             if (!mCheckedForLoaderManager) {
                 mCheckedForLoaderManager = true;
-                mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+                mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
             }
             if (mLoaderManager != null) {
                 mLoaderManager.doStart();
@@ -1521,7 +1556,7 @@
         //        + " mLoaderManager=" + mLoaderManager);
         if (!mCheckedForLoaderManager) {
             mCheckedForLoaderManager = true;
-            mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+            mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
         }
         if (mLoaderManager != null) {
             mLoaderManager.doDestroy();
@@ -1546,7 +1581,7 @@
         mBackStackNesting = 0;
         mFragmentManager = null;
         mChildFragmentManager = null;
-        mActivity = null;
+        mHost = null;
         mFragmentId = 0;
         mContainerId = 0;
         mTag = null;
@@ -2034,9 +2069,9 @@
             writer.print(prefix); writer.print("mFragmentManager=");
             writer.println(mFragmentManager);
         }
-        if (mActivity != null) {
-            writer.print(prefix); writer.print("mActivity=");
-            writer.println(mActivity);
+        if (mHost != null) {
+            writer.print(prefix); writer.print("mHost=");
+            writer.println(mHost);
         }
         if (mParentFragment != null) {
             writer.print(prefix); writer.print("mParentFragment=");
@@ -2094,10 +2129,10 @@
 
     void instantiateChildFragmentManager() {
         mChildFragmentManager = new FragmentManagerImpl();
-        mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() {
+        mChildFragmentManager.attachController(mHost, new FragmentContainer() {
             @Override
             @Nullable
-            public View findViewById(int id) {
+            public View onFindViewById(int id) {
                 if (mView == null) {
                     throw new IllegalStateException("Fragment does not have a view");
                 }
@@ -2105,7 +2140,7 @@
             }
 
             @Override
-            public boolean hasView() {
+            public boolean onHasView() {
                 return (mView != null);
             }
         }, this);
@@ -2319,13 +2354,13 @@
             mLoadersStarted = false;
             if (!mCheckedForLoaderManager) {
                 mCheckedForLoaderManager = true;
-                mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+                mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
             }
             if (mLoaderManager != null) {
-                if (mActivity == null || !mActivity.mChangingConfigurations) {
-                    mLoaderManager.doStop();
-                } else {
+                if (mRetaining) {
                     mLoaderManager.doRetain();
+                } else {
+                    mLoaderManager.doStop();
                 }
             }
         }
diff --git a/core/java/android/app/FragmentContainer.java b/core/java/android/app/FragmentContainer.java
new file mode 100644
index 0000000..b2e0300
--- /dev/null
+++ b/core/java/android/app/FragmentContainer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.IdRes;
+import android.annotation.Nullable;
+import android.view.View;
+
+/**
+ * Callbacks to a {@link Fragment}'s container.
+ */
+public abstract class FragmentContainer {
+    /**
+     * Return the view with the given resource ID. May return {@code null} if the
+     * view is not a child of this container.
+     */
+    @Nullable
+    public abstract View onFindViewById(@IdRes int id);
+
+    /**
+     * Return {@code true} if the container holds any view.
+     */
+    public abstract boolean onHasView();
+}
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
new file mode 100644
index 0000000..28dadfa
--- /dev/null
+++ b/core/java/android/app/FragmentController.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Provides integration points with a {@link FragmentManager} for a fragment host.
+ * <p>
+ * It is the responsibility of the host to take care of the Fragment's lifecycle.
+ * The methods provided by {@link FragmentController} are for that purpose.
+ */
+public class FragmentController {
+    private final FragmentHostCallback<?> mHost;
+
+    /**
+     * Returns a {@link FragmentController}.
+     */
+    public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
+        return new FragmentController(callbacks);
+    }
+
+    private FragmentController(FragmentHostCallback<?> callbacks) {
+        mHost = callbacks;
+    }
+
+    /**
+     * Returns a {@link FragmentManager} for this controller.
+     */
+    public FragmentManager getFragmentManager() {
+        return mHost.getFragmentManagerImpl();
+    }
+
+    /**
+     * Returns a {@link LoaderManager}.
+     */
+    public LoaderManager getLoaderManager() {
+        return mHost.getLoaderManagerImpl();
+    }
+
+    /**
+     * Returns a fragment with the given identifier.
+     */
+    @Nullable
+    public Fragment findFragmentByWho(String who) {
+        return mHost.mFragmentManager.findFragmentByWho(who);
+    }
+
+    /**
+     * Attaches the host to the FragmentManager for this controller. The host must be
+     * attached before the FragmentManager can be used to manage Fragments.
+     * */
+    public void attachHost(Fragment parent) {
+        mHost.mFragmentManager.attachController(
+                mHost, mHost /*container*/, parent);
+    }
+
+    /**
+     * Instantiates a Fragment's view.
+     *
+     * @param parent The parent that the created view will be placed
+     * in; <em>note that this may be null</em>.
+     * @param name Tag name to be inflated.
+     * @param context The context the view is being created in.
+     * @param attrs Inflation attributes as specified in XML file.
+     *
+     * @return view the newly created view
+     */
+    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+        return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
+    }
+
+    /**
+     * Marks the fragment state as unsaved. This allows for "state loss" detection.
+     */
+    public void noteStateNotSaved() {
+        mHost.mFragmentManager.noteStateNotSaved();
+    }
+
+    /**
+     * Saves the state for all Fragments.
+     */
+    public Parcelable saveAllState() {
+        return mHost.mFragmentManager.saveAllState();
+    }
+
+    /**
+     * Restores the saved state for all Fragments. The given Fragment list are Fragment
+     * instances retained across configuration changes.
+     *
+     * @see #retainNonConfig()
+     */
+    public void restoreAllState(Parcelable state, List<Fragment> nonConfigList) {
+        mHost.mFragmentManager.restoreAllState(state, nonConfigList);
+    }
+
+    /**
+     * Returns a list of Fragments that have opted to retain their instance across
+     * configuration changes.
+     */
+    public List<Fragment> retainNonConfig() {
+        return mHost.mFragmentManager.retainNonConfig();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the create state.
+     * <p>Call when Fragments should be created.
+     *
+     * @see Fragment#onCreate(Bundle)
+     */
+    public void dispatchCreate() {
+        mHost.mFragmentManager.dispatchCreate();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the activity created state.
+     * <p>Call when Fragments should be informed their host has been created.
+     *
+     * @see Fragment#onActivityCreated(Bundle)
+     */
+    public void dispatchActivityCreated() {
+        mHost.mFragmentManager.dispatchActivityCreated();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the start state.
+     * <p>Call when Fragments should be started.
+     *
+     * @see Fragment#onStart()
+     */
+    public void dispatchStart() {
+        mHost.mFragmentManager.dispatchStart();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the resume state.
+     * <p>Call when Fragments should be resumed.
+     *
+     * @see Fragment#onResume()
+     */
+    public void dispatchResume() {
+        mHost.mFragmentManager.dispatchResume();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the pause state.
+     * <p>Call when Fragments should be paused.
+     *
+     * @see Fragment#onPause()
+     */
+    public void dispatchPause() {
+        mHost.mFragmentManager.dispatchPause();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the stop state.
+     * <p>Call when Fragments should be stopped.
+     *
+     * @see Fragment#onStop()
+     */
+    public void dispatchStop() {
+        mHost.mFragmentManager.dispatchStop();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the destroy view state.
+     * <p>Call when the Fragment's views should be destroyed.
+     *
+     * @see Fragment#onDestroyView()
+     */
+    public void dispatchDestroyView() {
+        mHost.mFragmentManager.dispatchDestroyView();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the destroy state.
+     * <p>Call when Fragments should be destroyed.
+     *
+     * @see Fragment#onDestroy()
+     */
+    public void dispatchDestroy() {
+        mHost.mFragmentManager.dispatchDestroy();
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know a configuration change occurred.
+     * <p>Call when there is a configuration change.
+     *
+     * @see Fragment#onConfigurationChanged(Configuration)
+     */
+    public void dispatchConfigurationChanged(Configuration newConfig) {
+        mHost.mFragmentManager.dispatchConfigurationChanged(newConfig);
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know the device is in a low memory condition.
+     * <p>Call when the device is low on memory and Fragment's should trim
+     * their memory usage.
+     *
+     * @see Fragment#onLowMemory()
+     */
+    public void dispatchLowMemory() {
+        mHost.mFragmentManager.dispatchLowMemory();
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know they should trim their memory usage.
+     * <p>Call when the Fragment can release allocated memory [such as if
+     * the Fragment is in the background].
+     *
+     * @see Fragment#onTrimMemory(int)
+     */
+    public void dispatchTrimMemory(int level) {
+        mHost.mFragmentManager.dispatchTrimMemory(level);
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know they should create an options menu.
+     * <p>Call when the Fragment should create an options menu.
+     *
+     * @return {@code true} if the options menu contains items to display
+     * @see Fragment#onCreateOptionsMenu(Menu, MenuInflater)
+     */
+    public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        return mHost.mFragmentManager.dispatchCreateOptionsMenu(menu, inflater);
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know they should prepare their options menu for display.
+     * <p>Call immediately before displaying the Fragment's options menu.
+     *
+     * @return {@code true} if the options menu contains items to display
+     * @see Fragment#onPrepareOptionsMenu(Menu)
+     */
+    public boolean dispatchPrepareOptionsMenu(Menu menu) {
+        return mHost.mFragmentManager.dispatchPrepareOptionsMenu(menu);
+    }
+
+    /**
+     * Sends an option item selection event to the Fragments managed by the
+     * controller's FragmentManager. Once the event has been consumed,
+     * no additional handling will be performed.
+     * <p>Call immediately after an options menu item has been selected
+     *
+     * @return {@code true} if the options menu selection event was consumed
+     * @see Fragment#onOptionsItemSelected(MenuItem)
+     */
+    public boolean dispatchOptionsItemSelected(MenuItem item) {
+        return mHost.mFragmentManager.dispatchOptionsItemSelected(item);
+    }
+
+    /**
+     * Sends a context item selection event to the Fragments managed by the
+     * controller's FragmentManager. Once the event has been consumed,
+     * no additional handling will be performed.
+     * <p>Call immediately after an options menu item has been selected
+     *
+     * @return {@code true} if the context menu selection event was consumed
+     * @see Fragment#onContextItemSelected(MenuItem)
+     */
+    public boolean dispatchContextItemSelected(MenuItem item) {
+        return mHost.mFragmentManager.dispatchContextItemSelected(item);
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know their options menu has closed.
+     * <p>Call immediately after closing the Fragment's options menu.
+     *
+     * @see Fragment#onOptionsMenuClosed(Menu)
+     */
+    public void dispatchOptionsMenuClosed(Menu menu) {
+        mHost.mFragmentManager.dispatchOptionsMenuClosed(menu);
+    }
+
+    /**
+     * Execute any pending actions for the Fragments managed by the
+     * controller's FragmentManager.
+     * <p>Call when queued actions can be performed [eg when the
+     * Fragment moves into a start or resume state].
+     * @return {@code true} if queued actions were performed
+     */
+    public boolean execPendingActions() {
+        return mHost.mFragmentManager.execPendingActions();
+    }
+
+    /**
+     * Starts the loaders.
+     */
+    public void doLoaderStart() {
+        mHost.doLoaderStart();
+    }
+
+    /**
+     * Stops the loaders, optionally retaining their state. This is useful for keeping the
+     * loader state across configuration changes.
+     *
+     * @param retain When {@code true}, the loaders aren't stopped, but, their instances
+     * are retained in a started state
+     */
+    public void doLoaderStop(boolean retain) {
+        mHost.doLoaderStop(retain);
+    }
+
+    /**
+     * Destroys the loaders and, if their state is not being retained, removes them.
+     */
+    public void doLoaderDestroy() {
+        mHost.doLoaderDestroy();
+    }
+
+    /**
+     * Lets the loaders know the host is ready to receive notifications.
+     */
+    public void reportLoaderStart() {
+        mHost.reportLoaderStart();
+    }
+
+    /**
+     * Returns a list of LoaderManagers that have opted to retain their instance across
+     * configuration changes.
+     */
+    public ArrayMap<String, LoaderManager> retainLoaderNonConfig() {
+        return mHost.retainLoaderNonConfig();
+    }
+
+    /**
+     * Restores the saved state for all LoaderManagers. The given LoaderManager list are
+     * LoaderManager instances retained across configuration changes.
+     *
+     * @see #retainLoaderNonConfig()
+     */
+    public void restoreLoaderNonConfig(ArrayMap<String, LoaderManager> loaderManagers) {
+        mHost.restoreLoaderNonConfig(loaderManagers);
+    }
+
+    /**
+     * Dumps the current state of the loaders.
+     */
+    public void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        mHost.dumpLoaders(prefix, fd, writer, args);
+    }
+}
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
new file mode 100644
index 0000000..dad2c79
--- /dev/null
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Integration points with the Fragment host.
+ * <p>
+ * Fragments may be hosted by any object; such as an {@link Activity}. In order to
+ * host fragments, implement {@link FragmentHostCallback}, overriding the methods
+ * applicable to the host.
+ */
+public abstract class FragmentHostCallback<E> extends FragmentContainer {
+    private final Activity mActivity;
+    final Context mContext;
+    private final Handler mHandler;
+    final int mWindowAnimations;
+    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
+    private ArrayMap<String, LoaderManager> mAllLoaderManagers;
+    private LoaderManagerImpl mLoaderManager;
+    private boolean mCheckedForLoaderManager;
+    private boolean mLoadersStarted;
+
+    public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
+        this(null /*activity*/, context, handler, windowAnimations);
+    }
+
+    FragmentHostCallback(Activity activity) {
+        this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
+    }
+
+    FragmentHostCallback(Activity activity, Context context, Handler handler,
+            int windowAnimations) {
+        mActivity = activity;
+        mContext = context;
+        mHandler = handler;
+        mWindowAnimations = windowAnimations;
+    }
+
+    /**
+     * Print internal state into the given stream.
+     *
+     * @param prefix Desired prefix to prepend at each line of output.
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer The PrintWriter to which you should dump your state. This will be closed
+     *                  for you after you return.
+     * @param args additional arguments to the dump request.
+     */
+    public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+    }
+
+    /**
+     * Return {@code true} if the fragment's state needs to be saved.
+     */
+    public boolean onShouldSaveFragmentState(Fragment fragment) {
+        return true;
+    }
+
+    /**
+     * Return a {@link LayoutInflater}.
+     * See {@link Activity#getLayoutInflater()}.
+     */
+    public LayoutInflater onGetLayoutInflater() {
+        return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+    }
+
+    /**
+     * Return {@code true} if the FragmentManager's LayoutInflaterFactory should be used.
+     */
+    public boolean onUseFragmentManagerInflaterFactory() {
+        return false;
+    }
+
+    /**
+     * Return the object that's currently hosting the fragment. If a {@link Fragment}
+     * is hosted by a {@link Activity}, the object returned here should be the same
+     * object returned from {@link Fragment#getActivity()}.
+     */
+    @Nullable
+    public abstract E onGetHost();
+
+    /**
+     * Invalidates the activity's options menu.
+     * See {@link Activity#invalidateOptionsMenu()}
+     */
+    public void onInvalidateOptionsMenu() {
+    }
+
+    /**
+     * Starts a new {@link Activity} from the given fragment.
+     * See {@link Activity#startActivityForResult(Intent, int)}.
+     */
+    public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
+            Bundle options) {
+        if (requestCode != -1) {
+            throw new IllegalStateException(
+                    "Starting activity with a requestCode requires a FragmentActivity host");
+        }
+        mContext.startActivity(intent);
+    }
+
+    /**
+     * Return {@code true} if there are window animations.
+     */
+    public boolean onHasWindowAnimations() {
+        return true;
+    }
+
+    /**
+     * Return the window animations.
+     */
+    public int onGetWindowAnimations() {
+        return mWindowAnimations;
+    }
+
+    @Nullable
+    @Override
+    public View onFindViewById(int id) {
+        return null;
+    }
+
+    @Override
+    public boolean onHasView() {
+        return true;
+    }
+
+    Activity getActivity() {
+        return mActivity;
+    }
+
+    Context getContext() {
+        return mContext;
+    }
+
+    Handler getHandler() {
+        return mHandler;
+    }
+
+    FragmentManagerImpl getFragmentManagerImpl() {
+        return mFragmentManager;
+    }
+
+    LoaderManagerImpl getLoaderManagerImpl() {
+        if (mLoaderManager != null) {
+            return mLoaderManager;
+        }
+        mCheckedForLoaderManager = true;
+        mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true /*create*/);
+        return mLoaderManager;
+    }
+
+    void inactivateFragment(String who) {
+        //Log.v(TAG, "invalidateSupportFragment: who=" + who);
+        if (mAllLoaderManagers != null) {
+            LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
+            if (lm != null && !lm.mRetaining) {
+                lm.doDestroy();
+                mAllLoaderManagers.remove(who);
+            }
+        }
+    }
+
+    void onFragmentInflate(Fragment fragment, AttributeSet attrs, Bundle savedInstanceState) {
+        fragment.onInflate(mContext, attrs, savedInstanceState);
+    }
+
+    void onFragmentAttach(Fragment fragment) {
+        fragment.onAttach(mContext);
+    }
+
+    void doLoaderStart() {
+        if (mLoadersStarted) {
+            return;
+        }
+        mLoadersStarted = true;
+
+        if (mLoaderManager != null) {
+            mLoaderManager.doStart();
+        } else if (!mCheckedForLoaderManager) {
+            mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
+        }
+        mCheckedForLoaderManager = true;
+    }
+
+    void doLoaderStop(boolean retain) {
+        if (mLoaderManager == null) {
+            return;
+        }
+
+        if (!mLoadersStarted) {
+            return;
+        }
+        mLoadersStarted = false;
+
+        if (retain) {
+            mLoaderManager.doRetain();
+        } else {
+            mLoaderManager.doStop();
+        }
+    }
+
+    void doLoaderRetain() {
+        if (mLoaderManager == null) {
+            return;
+        }
+        mLoaderManager.doRetain();
+    }
+
+    void doLoaderDestroy() {
+        if (mLoaderManager == null) {
+            return;
+        }
+        mLoaderManager.doDestroy();
+    }
+
+    void reportLoaderStart() {
+        if (mAllLoaderManagers != null) {
+            final int N = mAllLoaderManagers.size();
+            LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
+            for (int i=N-1; i>=0; i--) {
+                loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
+            }
+            for (int i=0; i<N; i++) {
+                LoaderManagerImpl lm = loaders[i];
+                lm.finishRetain();
+                lm.doReportStart();
+            }
+        }
+    }
+
+    LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
+        if (mAllLoaderManagers == null) {
+            mAllLoaderManagers = new ArrayMap<String, LoaderManager>();
+        }
+        LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
+        if (lm == null) {
+            if (create) {
+                lm = new LoaderManagerImpl(who, this, started);
+                mAllLoaderManagers.put(who, lm);
+            }
+        } else {
+            lm.updateHostController(this);
+        }
+        return lm;
+    }
+
+    ArrayMap<String, LoaderManager> retainLoaderNonConfig() {
+        boolean retainLoaders = false;
+        if (mAllLoaderManagers != null) {
+            // prune out any loader managers that were already stopped and so
+            // have nothing useful to retain.
+            final int N = mAllLoaderManagers.size();
+            LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
+            for (int i=N-1; i>=0; i--) {
+                loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
+            }
+            for (int i=0; i<N; i++) {
+                LoaderManagerImpl lm = loaders[i];
+                if (lm.mRetaining) {
+                    retainLoaders = true;
+                } else {
+                    lm.doDestroy();
+                    mAllLoaderManagers.remove(lm.mWho);
+                }
+            }
+        }
+
+        if (retainLoaders) {
+            return mAllLoaderManagers;
+        }
+        return null;
+    }
+
+    void restoreLoaderNonConfig(ArrayMap<String, LoaderManager> loaderManagers) {
+        mAllLoaderManagers = loaderManagers;
+    }
+
+    void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        writer.print(prefix); writer.print("mLoadersStarted=");
+        writer.println(mLoadersStarted);
+        if (mLoaderManager != null) {
+            writer.print(prefix); writer.print("Loader Manager ");
+            writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
+            writer.println(":");
+            mLoaderManager.dump(prefix + "  ", fd, writer, args);
+        }
+    }
+}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 975b20d..62436e9 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -19,9 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
 import android.animation.AnimatorListenerAdapter;
-import android.annotation.Nullable;
 import android.content.Context;
-import android.annotation.IdRes;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.os.Bundle;
@@ -48,6 +46,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * Interface for interacting with {@link Fragment} objects inside of an
@@ -393,15 +392,6 @@
 }
 
 /**
- * Callbacks from FragmentManagerImpl to its container.
- */
-interface FragmentContainer {
-    @Nullable
-    public View findViewById(@IdRes int id);
-    public boolean hasView();
-}
-
-/**
  * Container for fragments associated with an activity.
  */
 final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
@@ -430,7 +420,8 @@
     ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
 
     int mCurState = Fragment.INITIALIZING;
-    Activity mActivity;
+    FragmentHostCallback<?> mHost;
+    FragmentController mController;
     FragmentContainer mContainer;
     Fragment mParent;
     
@@ -455,10 +446,10 @@
         Log.e(TAG, ex.getMessage());
         LogWriter logw = new LogWriter(Log.ERROR, TAG);
         PrintWriter pw = new FastPrintWriter(logw, false, 1024);
-        if (mActivity != null) {
+        if (mHost != null) {
             Log.e(TAG, "Activity state:");
             try {
-                mActivity.dump("  ", null, pw, new String[] { });
+                mHost.onDump("  ", null, pw, new String[] { });
             } catch (Exception e) {
                 pw.flush();
                 Log.e(TAG, "Failed dumping state", e);
@@ -490,7 +481,7 @@
     public void popBackStack() {
         enqueueAction(new Runnable() {
             @Override public void run() {
-                popBackStackState(mActivity.mHandler, null, -1, 0);
+                popBackStackState(mHost.getHandler(), null, -1, 0);
             }
         }, false);
     }
@@ -499,14 +490,14 @@
     public boolean popBackStackImmediate() {
         checkStateLoss();
         executePendingTransactions();
-        return popBackStackState(mActivity.mHandler, null, -1, 0);
+        return popBackStackState(mHost.getHandler(), null, -1, 0);
     }
 
     @Override
     public void popBackStack(final String name, final int flags) {
         enqueueAction(new Runnable() {
             @Override public void run() {
-                popBackStackState(mActivity.mHandler, name, -1, flags);
+                popBackStackState(mHost.getHandler(), name, -1, flags);
             }
         }, false);
     }
@@ -515,7 +506,7 @@
     public boolean popBackStackImmediate(String name, int flags) {
         checkStateLoss();
         executePendingTransactions();
-        return popBackStackState(mActivity.mHandler, name, -1, flags);
+        return popBackStackState(mHost.getHandler(), name, -1, flags);
     }
 
     @Override
@@ -525,7 +516,7 @@
         }
         enqueueAction(new Runnable() {
             @Override public void run() {
-                popBackStackState(mActivity.mHandler, null, id, flags);
+                popBackStackState(mHost.getHandler(), null, id, flags);
             }
         }, false);
     }
@@ -537,7 +528,7 @@
         if (id < 0) {
             throw new IllegalArgumentException("Bad id: " + id);
         }
-        return popBackStackState(mActivity.mHandler, null, id, flags);
+        return popBackStackState(mHost.getHandler(), null, id, flags);
     }
 
     @Override
@@ -619,7 +610,7 @@
         if (mParent != null) {
             DebugUtils.buildShortClassTag(mParent, sb);
         } else {
-            DebugUtils.buildShortClassTag(mActivity, sb);
+            DebugUtils.buildShortClassTag(mHost, sb);
         }
         sb.append("}}");
         return sb.toString();
@@ -716,7 +707,7 @@
         }
 
         writer.print(prefix); writer.println("FragmentManager misc state:");
-        writer.print(prefix); writer.print("  mActivity="); writer.println(mActivity);
+        writer.print(prefix); writer.print("  mHost="); writer.println(mHost);
         writer.print(prefix); writer.print("  mContainer="); writer.println(mContainer);
         if (mParent != null) {
             writer.print(prefix); writer.print("  mParent="); writer.println(mParent);
@@ -747,7 +738,7 @@
         }
         
         if (fragment.mNextAnim != 0) {
-            Animator anim = AnimatorInflater.loadAnimator(mActivity, fragment.mNextAnim);
+            Animator anim = AnimatorInflater.loadAnimator(mHost.getContext(), fragment.mNextAnim);
             if (anim != null) {
                 return anim;
             }
@@ -762,14 +753,14 @@
             return null;
         }
         
-        if (transitionStyle == 0 && mActivity.getWindow() != null) {
-            transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
+        if (transitionStyle == 0 && mHost.onHasWindowAnimations()) {
+            transitionStyle = mHost.onGetWindowAnimations();
         }
         if (transitionStyle == 0) {
             return null;
         }
         
-        TypedArray attrs = mActivity.obtainStyledAttributes(transitionStyle,
+        TypedArray attrs = mHost.getContext().obtainStyledAttributes(transitionStyle,
                 com.android.internal.R.styleable.FragmentAnimation);
         int anim = attrs.getResourceId(styleIndex, 0);
         attrs.recycle();
@@ -778,7 +769,7 @@
             return null;
         }
         
-        return AnimatorInflater.loadAnimator(mActivity, anim);
+        return AnimatorInflater.loadAnimator(mHost.getContext(), anim);
     }
     
     public void performPendingDeferredStart(Fragment f) {
@@ -848,18 +839,18 @@
                             }
                         }
                     }
-                    f.mActivity = mActivity;
+                    f.mHost = mHost;
                     f.mParentFragment = mParent;
                     f.mFragmentManager = mParent != null
-                            ? mParent.mChildFragmentManager : mActivity.mFragments;
+                            ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
                     f.mCalled = false;
-                    f.onAttach(mActivity);
+                    mHost.onFragmentAttach(f);
                     if (!f.mCalled) {
                         throw new SuperNotCalledException("Fragment " + f
                                 + " did not call through to super.onAttach()");
                     }
                     if (f.mParentFragment == null) {
-                        mActivity.onAttachFragment(f);
+                        mHost.onFragmentAttach(f);
                     }
 
                     if (!f.mRetaining) {
@@ -884,7 +875,7 @@
                         if (!f.mFromLayout) {
                             ViewGroup container = null;
                             if (f.mContainerId != 0) {
-                                container = (ViewGroup)mContainer.findViewById(f.mContainerId);
+                                container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
                                 if (container == null && !f.mRestored) {
                                     throwException(new IllegalArgumentException(
                                             "No view found for id 0x"
@@ -954,7 +945,7 @@
                         if (f.mView != null) {
                             // Need to save the current view state if not
                             // done already.
-                            if (!mActivity.isFinishing() && f.mSavedViewState == null) {
+                            if (!mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
                                 saveFragmentViewState(f);
                             }
                         }
@@ -1030,7 +1021,7 @@
                                 if (!f.mRetaining) {
                                     makeInactive(f);
                                 } else {
-                                    f.mActivity = null;
+                                    f.mHost = null;
                                     f.mParentFragment = null;
                                     f.mFragmentManager = null;
                                     f.mChildFragmentManager = null;
@@ -1053,7 +1044,7 @@
     }
     
     void moveToState(int newState, int transit, int transitStyle, boolean always) {
-        if (mActivity == null && newState != Fragment.INITIALIZING) {
+        if (mHost == null && newState != Fragment.INITIALIZING) {
             throw new IllegalStateException("No activity");
         }
 
@@ -1078,8 +1069,8 @@
                 startPendingDeferredFragments();
             }
 
-            if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
-                mActivity.invalidateOptionsMenu();
+            if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
+                mHost.onInvalidateOptionsMenu();
                 mNeedMenuInvalidate = false;
             }
         }
@@ -1126,7 +1117,7 @@
             mAvailIndices = new ArrayList<Integer>();
         }
         mAvailIndices.add(f.mIndex);
-        mActivity.invalidateFragment(f.mWho);
+        mHost.inactivateFragment(f.mWho);
         f.initState();
     }
     
@@ -1349,7 +1340,7 @@
             checkStateLoss();
         }
         synchronized (this) {
-            if (mDestroyed || mActivity == null) {
+            if (mDestroyed || mHost == null) {
                 throw new IllegalStateException("Activity has been destroyed");
             }
             if (mPendingActions == null) {
@@ -1357,8 +1348,8 @@
             }
             mPendingActions.add(action);
             if (mPendingActions.size() == 1) {
-                mActivity.mHandler.removeCallbacks(mExecCommit);
-                mActivity.mHandler.post(mExecCommit);
+                mHost.getHandler().removeCallbacks(mExecCommit);
+                mHost.getHandler().post(mExecCommit);
             }
         }
     }
@@ -1427,7 +1418,7 @@
             throw new IllegalStateException("Recursive entry to executePendingTransactions");
         }
         
-        if (Looper.myLooper() != mActivity.mHandler.getLooper()) {
+        if (Looper.myLooper() != mHost.getHandler().getLooper()) {
             throw new IllegalStateException("Must be called from main thread of process");
         }
 
@@ -1447,7 +1438,7 @@
                 }
                 mPendingActions.toArray(mTmpActions);
                 mPendingActions.clear();
-                mActivity.mHandler.removeCallbacks(mExecCommit);
+                mHost.getHandler().removeCallbacks(mExecCommit);
             }
             
             mExecutingActions = true;
@@ -1737,7 +1728,7 @@
         return fms;
     }
     
-    void restoreAllState(Parcelable state, ArrayList<Fragment> nonConfig) {
+    void restoreAllState(Parcelable state, List<Fragment> nonConfig) {
         // If there is no saved state at all, then there can not be
         // any nonConfig fragments either, so that is that.
         if (state == null) return;
@@ -1758,7 +1749,7 @@
                 f.mAdded = false;
                 f.mTarget = null;
                 if (fs.mSavedFragmentState != null) {
-                    fs.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
+                    fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
                     f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
                             FragmentManagerImpl.VIEW_STATE_TAG);
                     f.mSavedFragmentState = fs.mSavedFragmentState;
@@ -1775,7 +1766,7 @@
         for (int i=0; i<fms.mActive.length; i++) {
             FragmentState fs = fms.mActive[i];
             if (fs != null) {
-                Fragment f = fs.instantiate(mActivity, mParent);
+                Fragment f = fs.instantiate(mHost, mParent);
                 if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
                 mActive.add(f);
                 // Now that the fragment is instantiated (or came from being
@@ -1851,9 +1842,10 @@
         }
     }
     
-    public void attachActivity(Activity activity, FragmentContainer container, Fragment parent) {
-        if (mActivity != null) throw new IllegalStateException("Already attached");
-        mActivity = activity;
+    public void attachController(FragmentHostCallback<?> host, FragmentContainer container,
+            Fragment parent) {
+        if (mHost != null) throw new IllegalStateException("Already attached");
+        mHost = host;
         mContainer = container;
         mParent = parent;
     }
@@ -1898,7 +1890,7 @@
         mDestroyed = true;
         execPendingActions();
         moveToState(Fragment.INITIALIZING, false);
-        mActivity = null;
+        mHost = null;
         mContainer = null;
         mParent = null;
     }
@@ -2024,8 +2016,8 @@
 
     @Override
     public void invalidateOptionsMenu() {
-        if (mActivity != null && mCurState == Fragment.RESUMED) {
-            mActivity.invalidateOptionsMenu();
+        if (mHost != null && mCurState == Fragment.RESUMED) {
+            mHost.onInvalidateOptionsMenu();
         } else {
             mNeedMenuInvalidate = true;
         }
@@ -2115,7 +2107,7 @@
             fragment.mTag = tag;
             fragment.mInLayout = true;
             fragment.mFragmentManager = this;
-            fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+            mHost.onFragmentInflate(fragment, attrs, fragment.mSavedFragmentState);
             addFragment(fragment, true);
         } else if (fragment.mInLayout) {
             // A fragment already exists and it is not one we restored from
@@ -2132,7 +2124,7 @@
             // from last saved state), then give it the attributes to
             // initialize itself.
             if (!fragment.mRetaining) {
-                fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+                mHost.onFragmentInflate(fragment, attrs, fragment.mSavedFragmentState);
             }
         }
 
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index b13b24a..f0e35c9 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -214,12 +214,12 @@
 
     final String mWho;
 
-    Activity mActivity;
     boolean mStarted;
     boolean mRetaining;
     boolean mRetainingStarted;
     
     boolean mCreatingLoader;
+    private FragmentHostCallback mHost;
 
     final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,
             Loader.OnLoadCanceledListener<Object> {
@@ -356,15 +356,15 @@
             if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
                 if (DEBUG) Log.v(TAG, "  Reseting: " + this);
                 String lastBecause = null;
-                if (mActivity != null) {
-                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
-                    mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset";
+                if (mHost != null) {
+                    lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
+                    mHost.mFragmentManager.mNoTransactionsBecause = "onLoaderReset";
                 }
                 try {
                     mCallbacks.onLoaderReset(mLoader);
                 } finally {
-                    if (mActivity != null) {
-                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+                    if (mHost != null) {
+                        mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
                     }
                 }
             }
@@ -465,25 +465,25 @@
                 mInactiveLoaders.remove(mId);
             }
 
-            if (mActivity != null && !hasRunningLoaders()) {
-                mActivity.mFragments.startPendingDeferredFragments();
+            if (mHost != null && !hasRunningLoaders()) {
+                mHost.mFragmentManager.startPendingDeferredFragments();
             }
         }
 
         void callOnLoadFinished(Loader<Object> loader, Object data) {
             if (mCallbacks != null) {
                 String lastBecause = null;
-                if (mActivity != null) {
-                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
-                    mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
+                if (mHost != null) {
+                    lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
+                    mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished";
                 }
                 try {
                     if (DEBUG) Log.v(TAG, "  onLoadFinished in " + loader + ": "
                             + loader.dataToString(data));
                     mCallbacks.onLoadFinished(loader, data);
                 } finally {
-                    if (mActivity != null) {
-                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+                    if (mHost != null) {
+                        mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
                     }
                 }
                 mDeliveredData = true;
@@ -530,14 +530,14 @@
         }
     }
     
-    LoaderManagerImpl(String who, Activity activity, boolean started) {
+    LoaderManagerImpl(String who, FragmentHostCallback host, boolean started) {
         mWho = who;
-        mActivity = activity;
+        mHost = host;
         mStarted = started;
     }
     
-    void updateActivity(Activity activity) {
-        mActivity = activity;
+    void updateHostController(FragmentHostCallback host) {
+        mHost = host;
     }
     
     private LoaderInfo createLoader(int id, Bundle args,
@@ -730,8 +730,8 @@
             mInactiveLoaders.removeAt(idx);
             info.destroy();
         }
-        if (mActivity != null && !hasRunningLoaders()) {
-            mActivity.mFragments.startPendingDeferredFragments();
+        if (mHost != null && !hasRunningLoaders()) {
+            mHost.mFragmentManager.startPendingDeferredFragments();
         }
     }
 
@@ -849,7 +849,7 @@
         sb.append("LoaderManager{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(" in ");
-        DebugUtils.buildShortClassTag(mActivity, sb);
+        DebugUtils.buildShortClassTag(mHost, sb);
         sb.append("}}");
         return sb.toString();
     }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 3044a94..9b4dcc6 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -34,6 +34,7 @@
 import android.os.ServiceManager;
 import android.app.ActivityThread;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.os.Binder;
 import android.util.Log;
 import android.util.Pair;
@@ -389,7 +390,7 @@
      * @hide
      */
     public static final String ACTION_BLE_STATE_CHANGED =
-        "anrdoid.bluetooth.adapter.action.BLE_STATE_CHANGED";
+        "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
 
     /**
      * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
@@ -632,24 +633,6 @@
     }
 
     /**
-     * Returns true if LE only mode is enabled, that is apps
-     * have authorization to turn only BT ON and the calling
-     * app has privilage to do so
-     */
-    private boolean isLEAlwaysOnEnabled() {
-        boolean ret = false;
-        if (SystemProperties.getBoolean("ro.bluetooth.blealwayson", true) == true) {
-            Log.v(TAG, "LE always on mode is enabled");
-            // TODO: System API authorization check
-            ret = true;
-        } else {
-            Log.v(TAG, "LE always on mode is disabled");
-            ret = false;
-        }
-        return ret;
-    }
-
-    /**
      * Turns off Bluetooth LE which was earlier turned on by calling EnableBLE().
      *
      * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
@@ -676,7 +659,7 @@
      * @hide
      */
     public boolean disableBLE() {
-        if (isLEAlwaysOnEnabled() != true) return false;
+        if (!isBleScanAlwaysAvailable()) return false;
 
         int state = getLeState();
         if (state == BluetoothAdapter.STATE_ON) {
@@ -738,7 +721,7 @@
      * @hide
      */
     public boolean enableBLE() {
-        if (isLEAlwaysOnEnabled() != true) return false;
+        if (!isBleScanAlwaysAvailable()) return false;
 
         if (isLeEnabled() == true) {
             if (DBG) Log.d(TAG, "enableBLE(): BT is already enabled..!");
@@ -1243,8 +1226,12 @@
      */
     @SystemApi
     public boolean isBleScanAlwaysAvailable() {
-        // TODO: implement after Settings UI change.
-        return false;
+        try {
+            return mManagerService.isBleScanAlwaysAvailable();
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
+            return false;
+        }
     }
 
     /**
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
index 8d1ce99..0b81ee8 100644
--- a/core/java/android/bluetooth/IBluetoothManager.aidl
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -44,6 +44,8 @@
 
     String getAddress();
     String getName();
+
+    boolean isBleScanAlwaysAvailable();
     int updateBleAppCount(IBinder b, boolean enable);
     boolean isBleAppPresent();
 }
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index 123514e..dad486d 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -187,7 +187,7 @@
         mScanResultType = scanResultType;
         mReportDelayMillis = reportDelayMillis;
         mNumOfMatchesPerFilter = numOfMatchesPerFilter;
-        mMatchMode = numOfMatchesPerFilter;
+        mMatchMode = matchMode;
     }
 
     private ScanSettings(Parcel in) {
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 0cf8df1..aeddf03 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -114,6 +114,11 @@
      * the Surface provided to prepare must not be used as a target of a CaptureRequest submitted
      * to this session.</p>
      *
+     * <p>{@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}
+     * devices cannot pre-allocate output buffers; for those devices,
+     * {@link StateCallback#onSurfacePrepared} will be immediately called, and no preallocation is
+     * done.</p>
+     *
      * @param surface the output Surface for which buffers should be pre-allocated. Must be one of
      * the output Surfaces used to create this session.
      *
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index abe26ea..edad00f 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -202,6 +202,7 @@
         private static final int CAMERA_IDLE = 1;
         private static final int CAPTURE_STARTED = 2;
         private static final int RESULT_RECEIVED = 3;
+        private static final int PREPARED = 4;
 
         private final HandlerThread mHandlerThread;
         private Handler mHandler;
@@ -253,7 +254,9 @@
 
         @Override
         public void onPrepared(int streamId) {
-            // TODO
+            Message msg = getHandler().obtainMessage(PREPARED,
+                    /*arg1*/ streamId, /*arg2*/ 0);
+            getHandler().sendMessage(msg);
         }
 
         @Override
@@ -301,6 +304,11 @@
                             mCallbacks.onResultReceived(result, resultExtras);
                             break;
                         }
+                        case PREPARED: {
+                            int streamId = msg.arg1;
+                            mCallbacks.onPrepared(streamId);
+                            break;
+                        }
                         default:
                             throw new IllegalArgumentException(
                                 "Unknown callback message " + msg.what);
@@ -631,7 +639,9 @@
             return CameraBinderDecorator.ENODEV;
         }
 
-        // TODO: Implement and fire callback
+        // LEGACY doesn't support actual prepare, just signal success right away
+        mCameraCallbacks.onPrepared(streamId);
+
         return CameraBinderDecorator.NO_ERROR;
     }
 
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 9f344ad..cf96145 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -434,7 +434,8 @@
             mAuthenticationCallback = callback;
             mCryptoObject = crypto;
             long sessionId = crypto != null ? crypto.getOpId() : 0;
-            mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags);
+            mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
+                    mContext.getOpPackageName());
         } catch (RemoteException e) {
             Log.w(TAG, "Remote exception while authenticating: ", e);
             if (callback != null) {
@@ -555,7 +556,7 @@
      */
     public List<Fingerprint> getEnrolledFingerprints(int userId) {
         if (mService != null) try {
-            return mService.getEnrolledFingerprints(userId);
+            return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
         } catch (RemoteException e) {
             Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
         }
@@ -579,7 +580,8 @@
      */
     public boolean hasEnrolledFingerprints() {
         if (mService != null) try {
-            return mService.hasEnrolledFingerprints(UserHandle.myUserId());
+            return mService.hasEnrolledFingerprints(UserHandle.myUserId(),
+                    mContext.getOpPackageName());
         } catch (RemoteException e) {
             Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
         }
@@ -595,7 +597,7 @@
         if (mService != null) {
             try {
                 long deviceId = 0; /* TODO: plumb hardware id to FPMS */
-                return mService.isHardwareDetected(deviceId);
+                return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
             }
@@ -614,7 +616,7 @@
     public long getAuthenticatorId() {
         if (mService != null) {
             try {
-                return mService.getAuthenticatorId();
+                return mService.getAuthenticatorId(mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
             }
@@ -624,7 +626,13 @@
         return 0;
     }
 
-    private Handler mHandler = new Handler() {
+    private Handler mHandler;
+
+    private class MyHandler extends Handler {
+        private MyHandler(Context context) {
+            super(context.getMainLooper());
+        }
+
         public void handleMessage(android.os.Message msg) {
             switch(msg.what) {
                 case MSG_ENROLL_RESULT:
@@ -709,6 +717,7 @@
         if (mService == null) {
             Slog.v(TAG, "FingerprintManagerService was null");
         }
+        mHandler = new MyHandler(context);
     }
 
     private int getCurrentUserId() {
@@ -736,7 +745,7 @@
 
     private void cancelAuthentication(CryptoObject cryptoObject) {
         if (mService != null) try {
-            mService.cancelAuthentication(mToken);
+            mService.cancelAuthentication(mToken, mContext.getOpPackageName());
         } catch (RemoteException e) {
             if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
         }
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index c5ec08c..0484806 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -27,10 +27,10 @@
 interface IFingerprintService {
     // Authenticate the given sessionId with a fingerprint
     void authenticate(IBinder token, long sessionId, int groupId,
-            IFingerprintServiceReceiver receiver, int flags);
+            IFingerprintServiceReceiver receiver, int flags, String opPackageName);
 
     // Cancel authentication for the given sessionId
-    void cancelAuthentication(IBinder token);
+    void cancelAuthentication(IBinder token, String opPackageName);
 
     // Start fingerprint enrollment
     void enroll(IBinder token, in byte [] cryptoToken, int groupId, IFingerprintServiceReceiver receiver,
@@ -46,16 +46,16 @@
     void rename(int fingerId, int groupId, String name);
 
     // Get a list of enrolled fingerprints in the given group.
-    List<Fingerprint> getEnrolledFingerprints(int groupId);
+    List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName);
 
     // Determine if HAL is loaded and ready
-    boolean isHardwareDetected(long deviceId);
+    boolean isHardwareDetected(long deviceId, String opPackageName);
 
     // Get a pre-enrollment authentication token
     long preEnroll(IBinder token);
 
     // Determine if a user has at least one enrolled fingerprint
-    boolean hasEnrolledFingerprints(int groupId);
+    boolean hasEnrolledFingerprints(int groupId, String opPackageName);
 
     // Gets the number of hardware devices
     // int getHardwareDeviceCount();
@@ -64,5 +64,5 @@
     // long getHardwareDevice(int i);
 
     // Gets the authenticator ID for fingerprint
-    long getAuthenticatorId();
+    long getAuthenticatorId(String opPackageName);
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c531e7e..2d63e3f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -341,7 +341,8 @@
      * one.  This is used by applications needing to talk to the carrier's
      * Multimedia Messaging Service servers.
      *
-     * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+     * @deprecated Applications should instead use
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
      *         provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability.
      */
     public static final int TYPE_MOBILE_MMS  = 2;
@@ -351,7 +352,8 @@
      * one.  This is used by applications needing to talk to the carrier's
      * Secure User Plane Location servers for help locating the device.
      *
-     * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+     * @deprecated Applications should instead use
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
      *         provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability.
      */
     public static final int TYPE_MOBILE_SUPL = 3;
@@ -367,7 +369,8 @@
      * same network interface as {@link #TYPE_MOBILE} but the routing setup
      * is different.
      *
-     * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+     * @deprecated Applications should instead use
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
      *         uses the {@link NetworkCapabilities#TRANSPORT_CELLULAR} transport.
      */
     public static final int TYPE_MOBILE_HIPRI = 5;
@@ -910,7 +913,8 @@
      * implementation+feature combination, except that the value {@code -1}
      * always indicates failure.
      *
-     * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
+     * @deprecated Deprecated in favor of the cleaner
+     *             {@link #requestNetwork(NetworkRequest, NetworkCallback)} API.
      * @removed
      */
     public int startUsingNetworkFeature(int networkType, String feature) {
@@ -958,7 +962,7 @@
      * implementation+feature combination, except that the value {@code -1}
      * always indicates failure.
      *
-     * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
+     * @deprecated Deprecated in favor of the cleaner {@link unregisterNetworkCallback} API.
      * @removed
      */
     public int stopUsingNetworkFeature(int networkType, String feature) {
@@ -1236,8 +1240,9 @@
      * @param hostAddress the IP address of the host to which the route is desired
      * @return {@code true} on success, {@code false} on failure
      *
-     * @deprecated Deprecated in favor of the {@link #requestNetwork},
-     *             {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} api.
+     * @deprecated Deprecated in favor of the
+     *             {@link #requestNetwork(NetworkRequest, NetworkCallback)},
+     *             {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} API.
      * @removed
      */
     public boolean requestRouteToHost(int networkType, int hostAddress) {
@@ -1256,7 +1261,7 @@
      * @return {@code true} on success, {@code false} on failure
      * @hide
      * @deprecated Deprecated in favor of the {@link #requestNetwork} and
-     *             {@link #bindProcessToNetwork} api.
+     *             {@link #bindProcessToNetwork} API.
      * @removed
      */
     public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
@@ -2144,14 +2149,22 @@
         public static final int CANCELED     = 8;
 
         /**
-         * @hide
-         * Called whenever the framework connects to a network that it may use to
-         * satisfy this request
+         * Called when the framework connects to a new network to evaluate whether it satisfies this
+         * request. If evaluation succeeds, this callback may be followed by an {@link #onAvailable}
+         * callback. There is no guarantee that this new network will satisfy any requests, or that
+         * the network will stay connected for longer than the time necessary to evaluate it.
+         * <p>
+         * Most applications <b>should not</b> act on this callback, and should instead use
+         * {@link #onAvailable}. This callback is intended for use by applications that can assist
+         * the framework in properly evaluating the network &mdash; for example, an application that
+         * can automatically log in to a captive portal without user intervention.
+         *
+         * @param network The {@link Network} of the network that is being evaluated.
          */
         public void onPreCheck(Network network) {}
 
         /**
-         * Called when the framework connects and has declared new network ready for use.
+         * Called when the framework connects and has declared a new network ready for use.
          * This callback may be called more than once if the {@link Network} that is
          * satisfying the request changes.
          *
@@ -2251,116 +2264,82 @@
         @Override
         public void handleMessage(Message message) {
             Log.d(TAG, "CM callback handler got msg " + message.what);
+            NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class);
+            Network network = (Network) getObject(message, Network.class);
             switch (message.what) {
                 case CALLBACK_PRECHECK: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        callbacks.onPreCheck((Network)getObject(message, Network.class));
-                    } else {
-                        Log.e(TAG, "callback not found for PRECHECK message");
+                    NetworkCallback callback = getCallback(request, "PRECHECK");
+                    if (callback != null) {
+                        callback.onPreCheck(network);
                     }
                     break;
                 }
                 case CALLBACK_AVAILABLE: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        callbacks.onAvailable((Network)getObject(message, Network.class));
-                    } else {
-                        Log.e(TAG, "callback not found for AVAILABLE message");
+                    NetworkCallback callback = getCallback(request, "AVAILABLE");
+                    if (callback != null) {
+                        callback.onAvailable(network);
                     }
                     break;
                 }
                 case CALLBACK_LOSING: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        callbacks.onLosing((Network)getObject(message, Network.class),
-                                message.arg1);
-                    } else {
-                        Log.e(TAG, "callback not found for LOSING message");
+                    NetworkCallback callback = getCallback(request, "LOSING");
+                    if (callback != null) {
+                        callback.onLosing(network, message.arg1);
                     }
                     break;
                 }
                 case CALLBACK_LOST: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        callbacks.onLost((Network)getObject(message, Network.class));
-                    } else {
-                        Log.e(TAG, "callback not found for LOST message");
+                    NetworkCallback callback = getCallback(request, "LOST");
+                    if (callback != null) {
+                        callback.onLost(network);
                     }
                     break;
                 }
                 case CALLBACK_UNAVAIL: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = null;
-                    synchronized(mCallbackMap) {
-                        callbacks = mCallbackMap.get(request);
-                    }
-                    if (callbacks != null) {
-                        callbacks.onUnavailable();
-                    } else {
-                        Log.e(TAG, "callback not found for UNAVAIL message");
+                    NetworkCallback callback = getCallback(request, "UNAVAIL");
+                    if (callback != null) {
+                        callback.onUnavailable();
                     }
                     break;
                 }
                 case CALLBACK_CAP_CHANGED: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        Network network = (Network)getObject(message, Network.class);
+                    NetworkCallback callback = getCallback(request, "CAP_CHANGED");
+                    if (callback != null) {
                         NetworkCapabilities cap = (NetworkCapabilities)getObject(message,
                                 NetworkCapabilities.class);
 
-                        callbacks.onCapabilitiesChanged(network, cap);
-                    } else {
-                        Log.e(TAG, "callback not found for CAP_CHANGED message");
+                        callback.onCapabilitiesChanged(network, cap);
                     }
                     break;
                 }
                 case CALLBACK_IP_CHANGED: {
-                    NetworkRequest request = (NetworkRequest)getObject(message,
-                            NetworkRequest.class);
-                    NetworkCallback callbacks = getCallbacks(request);
-                    if (callbacks != null) {
-                        Network network = (Network)getObject(message, Network.class);
+                    NetworkCallback callback = getCallback(request, "IP_CHANGED");
+                    if (callback != null) {
                         LinkProperties lp = (LinkProperties)getObject(message,
                                 LinkProperties.class);
 
-                        callbacks.onLinkPropertiesChanged(network, lp);
-                    } else {
-                        Log.e(TAG, "callback not found for IP_CHANGED message");
+                        callback.onLinkPropertiesChanged(network, lp);
                     }
                     break;
                 }
                 case CALLBACK_RELEASED: {
-                    NetworkRequest req = (NetworkRequest)getObject(message, NetworkRequest.class);
-                    NetworkCallback callbacks = null;
+                    NetworkCallback callback = null;
                     synchronized(mCallbackMap) {
-                        callbacks = mCallbackMap.remove(req);
+                        callback = mCallbackMap.remove(request);
                     }
-                    if (callbacks != null) {
+                    if (callback != null) {
                         synchronized(mRefCount) {
                             if (mRefCount.decrementAndGet() == 0) {
                                 getLooper().quit();
                             }
                         }
                     } else {
-                        Log.e(TAG, "callback not found for CANCELED message");
+                        Log.e(TAG, "callback not found for RELEASED message");
                     }
                     break;
                 }
                 case CALLBACK_EXIT: {
-                    Log.d(TAG, "Listener quiting");
+                    Log.d(TAG, "Listener quitting");
                     getLooper().quit();
                     break;
                 }
@@ -2374,10 +2353,16 @@
         private Object getObject(Message msg, Class c) {
             return msg.getData().getParcelable(c.getSimpleName());
         }
-        private NetworkCallback getCallbacks(NetworkRequest req) {
+
+        private NetworkCallback getCallback(NetworkRequest req, String name) {
+            NetworkCallback callback;
             synchronized(mCallbackMap) {
-                return mCallbackMap.get(req);
+                callback = mCallbackMap.get(req);
             }
+            if (callback == null) {
+                Log.e(TAG, "callback not found for " + name + " message");
+            }
+            return callback;
         }
     }
 
@@ -2601,10 +2586,10 @@
 
     /**
      * Unregisters callbacks about and possibly releases networks originating from
-     * {@link #requestNetwork} and {@link #registerNetworkCallback} calls.  If the
-     * given {@code NetworkCallback} had previously been used with {@code #requestNetwork},
-     * any networks that had been connected to only to satisfy that request will be
-     * disconnected.
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and {@link #registerNetworkCallback}
+     * calls.  If the given {@code NetworkCallback} had previously been used with
+     * {@code #requestNetwork}, any networks that had been connected to only to satisfy that request
+     * will be disconnected.
      *
      * @param networkCallback The {@link NetworkCallback} used when making the request.
      */
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8c8bfab..ab70485 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -37,6 +37,11 @@
      * @hide
      */
     public NetworkCapabilities() {
+        clearAll();
+        mNetworkCapabilities =
+                (1 << NET_CAPABILITY_NOT_RESTRICTED) |
+                (1 << NET_CAPABILITY_TRUSTED) |
+                (1 << NET_CAPABILITY_NOT_VPN);
     }
 
     public NetworkCapabilities(NetworkCapabilities nc) {
@@ -50,11 +55,21 @@
     }
 
     /**
+     * Completely clears the contents of this object, removing even the capabilities that are set
+     * by default when the object is constructed.
+     * @hide
+     */
+    public void clearAll() {
+        mNetworkCapabilities = mTransportTypes = 0;
+        mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = 0;
+        mNetworkSpecifier = null;
+    }
+
+    /**
      * Represents the network's capabilities.  If any are specified they will be satisfied
      * by any Network that matches all of them.
      */
-    private long mNetworkCapabilities = (1 << NET_CAPABILITY_NOT_RESTRICTED) |
-            (1 << NET_CAPABILITY_TRUSTED) | (1 << NET_CAPABILITY_NOT_VPN);
+    private long mNetworkCapabilities;
 
     /**
      * Indicates this is a network that has the ability to reach the
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index d8834fe..0e2b8ba 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -238,6 +238,8 @@
         sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_EC_FIELD, "Unsupported EC field");
         sErrorCodeToString.put(KM_ERROR_MISSING_NONCE, "Required IV missing");
         sErrorCodeToString.put(KM_ERROR_INVALID_NONCE, "Invalid IV");
+        sErrorCodeToString.put(KM_ERROR_CALLER_NONCE_PROHIBITED,
+                "Caller-provided IV not permitted");
         sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
         sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
     }
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index cc090ad5..6651b83 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -52,6 +52,11 @@
     public static final int CALENDAR_DATE = 5;
 
     /**
+     * The user has touched the screen with a stylus and pressed the stylus button.
+     */
+    public static final int STYLUS_BUTTON_PRESS = 6;
+
+    /**
      * This is a private constant.  Feel free to renumber as desired.
      * @hide
      */
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 457d6ad..1503728 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -946,25 +946,21 @@
                                 attrs, R.styleable.Include);
                         final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
                         final int visibility = a.getInt(R.styleable.Include_visibility, -1);
-                        final boolean hasWidth = a.hasValue(R.styleable.Include_layout_width);
-                        final boolean hasHeight = a.hasValue(R.styleable.Include_layout_height);
                         a.recycle();
 
-                        // We try to load the layout params set in the <include /> tag. If
-                        // they don't exist, we will rely on the layout params set in the
-                        // included XML file.
-                        // During a layoutparams generation, a runtime exception is thrown
-                        // if either layout_width or layout_height is missing. We catch
-                        // this exception and set localParams accordingly: true means we
-                        // successfully loaded layout params from the <include /> tag,
-                        // false means we need to rely on the included layout params.
+                        // We try to load the layout params set in the <include /> tag.
+                        // If the parent can't generate layout params (ex. missing width
+                        // or height for the framework ViewGroups, though this is not
+                        // necessarily true of all ViewGroups) then we expect it to throw
+                        // a runtime exception.
+                        // We catch this exception and set localParams accordingly: true
+                        // means we successfully loaded layout params from the <include>
+                        // tag, false means we need to rely on the included layout params.
                         ViewGroup.LayoutParams params = null;
-                        if (hasWidth && hasHeight) {
-                            try {
-                                params = group.generateLayoutParams(attrs);
-                            } catch (RuntimeException e) {
-                                // Ignore, just fail over to child attrs.
-                            }
+                        try {
+                            params = group.generateLayoutParams(attrs);
+                        } catch (RuntimeException e) {
+                            // Ignore, just fail over to child attrs.
                         }
                         if (params == null) {
                             params = group.generateLayoutParams(childAttrs);
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 5e45c8f..5df596a 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -3180,6 +3180,18 @@
         return (getButtonState() & button) == button;
     }
 
+    /**
+     * Checks if a stylus is being used and if the first stylus button is
+     * pressed.
+     *
+     * @return True if the tool is a stylus and if the first stylus button is
+     *         pressed.
+     * @see #BUTTON_SECONDARY
+     */
+    public final boolean isStylusButtonPressed() {
+        return (isButtonPressed(BUTTON_SECONDARY) && getToolType(0) == TOOL_TYPE_STYLUS);
+    }
+
     public static final Parcelable.Creator<MotionEvent> CREATOR
             = new Parcelable.Creator<MotionEvent>() {
         public MotionEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b5b7f0f..81ad5ad 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -987,6 +987,17 @@
      */
     static final int DUPLICATE_PARENT_STATE = 0x00400000;
 
+    /**
+     * <p>
+     * Indicates this view can be stylus button pressed. When stylus button
+     * pressable, a View reacts to stylus button presses by notifiying
+     * the OnStylusButtonPressListener.
+     * </p>
+     * {@hide}
+     */
+    static final int STYLUS_BUTTON_PRESSABLE = 0x00800000;
+
+
     /** @hide */
     @IntDef({
         SCROLLBARS_INSIDE_OVERLAY,
@@ -3270,6 +3281,13 @@
         protected OnLongClickListener mOnLongClickListener;
 
         /**
+         * Listener used to dispatch stylus touch and button press events. This field should be made
+         * private, so it is hidden from the SDK.
+         * {@hide}
+         */
+        protected OnStylusButtonPressListener mOnStylusButtonPressListener;
+
+        /**
          * Listener used to build the context menu.
          * This field should be made private, so it is hidden from the SDK.
          * {@hide}
@@ -3360,6 +3378,13 @@
     private boolean mHasPerformedLongPress;
 
     /**
+     * Whether the stylus button is currently pressed down. This is true when
+     * the stylus is touching the screen and the button has been pressed, this
+     * is false once the stylus has been lifted.
+     */
+    private boolean mInStylusButtonPress = false;
+
+    /**
      * The minimum height of the view. We'll try our best to have the height
      * of this view to at least this amount.
      */
@@ -3875,6 +3900,12 @@
                         viewFlagMasks |= LONG_CLICKABLE;
                     }
                     break;
+                case com.android.internal.R.styleable.View_stylusButtonPressable:
+                    if (a.getBoolean(attr, false)) {
+                        viewFlagValues |= STYLUS_BUTTON_PRESSABLE;
+                        viewFlagMasks |= STYLUS_BUTTON_PRESSABLE;
+                    }
+                    break;
                 case com.android.internal.R.styleable.View_saveEnabled:
                     if (!a.getBoolean(attr, true)) {
                         viewFlagValues |= SAVE_DISABLED;
@@ -4340,6 +4371,7 @@
         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
+        out.append((mViewFlags & STYLUS_BUTTON_PRESSABLE) != 0 ? 'S' : '.');
         out.append(' ');
         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
@@ -4835,6 +4867,20 @@
     }
 
     /**
+     * Register a callback to be invoked when this view is touched with a stylus and the button is
+     * pressed.
+     *
+     * @param l The callback that will run
+     * @see #setStylusButtonPressable(boolean)
+     */
+    public void setOnStylusButtonPressListener(@Nullable OnStylusButtonPressListener l) {
+        if (!isStylusButtonPressable()) {
+            setStylusButtonPressable(true);
+        }
+        getListenerInfo().mOnStylusButtonPressListener = l;
+    }
+
+    /**
      * Register a callback to be invoked when the context menu for this view is
      * being built. If this view is not long clickable, it becomes long clickable.
      *
@@ -4912,6 +4958,46 @@
     }
 
     /**
+     * Call this view's OnStylusButtonPressListener, if it is defined.
+     *
+     * @return True if there was an assigned OnStylusButtonPressListener that consumed the event,
+     *         false otherwise.
+     */
+    public boolean performStylusButtonPress() {
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_STYLUS_BUTTON_PRESSED);
+
+        boolean handled = false;
+        ListenerInfo li = mListenerInfo;
+        if (li != null && li.mOnStylusButtonPressListener != null) {
+            handled = li.mOnStylusButtonPressListener.onStylusButtonPress(View.this);
+        }
+        if (handled) {
+            performHapticFeedback(HapticFeedbackConstants.STYLUS_BUTTON_PRESS);
+        }
+        return handled;
+    }
+
+    /**
+     * Checks for a stylus button press and calls the listener.
+     *
+     * @param event The event.
+     * @return True if the event was consumed.
+     */
+    private boolean performStylusActionOnButtonPress(MotionEvent event) {
+        if (isStylusButtonPressable() && !mInStylusButtonPress
+                && !mHasPerformedLongPress && event.isStylusButtonPressed()) {
+            if (performStylusButtonPress()) {
+                mInStylusButtonPress = true;
+                setPressed(true, event.getX(), event.getY());
+                removeTapCallback();
+                removeLongPressCallback();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Performs button-related actions during a touch down event.
      *
      * @param event The event.
@@ -5701,6 +5787,7 @@
      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
+     *   <li>{@link AccessibilityNodeInfo#setStylusButtonPressable(boolean)}</li>
      * </ul>
      * <p>
      * Subclasses should override this method, call the super implementation,
@@ -5852,6 +5939,9 @@
                 structure.setChecked(true);
             }
         }
+        if (isStylusButtonPressable()) {
+            structure.setStylusButtonPressable(true);
+        }
         structure.setClassName(getAccessibilityClassName().toString());
         structure.setContentDescription(getContentDescription());
     }
@@ -5909,6 +5999,9 @@
                 structure.setChecked(true);
             }
         }
+        if (info.isStylusButtonPressable()) {
+            structure.setStylusButtonPressable(true);
+        }
         CharSequence cname = info.getClassName();
         structure.setClassName(cname != null ? cname.toString() : null);
         structure.setContentDescription(info.getContentDescription());
@@ -6038,6 +6131,7 @@
         info.setAccessibilityFocused(isAccessibilityFocused());
         info.setSelected(isSelected());
         info.setLongClickable(isLongClickable());
+        info.setStylusButtonPressable(isStylusButtonPressable());
         info.setLiveRegion(getAccessibilityLiveRegion());
 
         // TODO: These make sense only if we are in an AdapterView but all
@@ -6068,6 +6162,10 @@
             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
         }
 
+        if (isStylusButtonPressable() && isEnabled()) {
+            info.addAction(AccessibilityAction.ACTION_STYLUS_BUTTON_PRESS);
+        }
+
         CharSequence text = getIterableTextForAccessibility();
         if (text != null && text.length() > 0) {
             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
@@ -7442,6 +7540,31 @@
     }
 
     /**
+     * Indicates whether this view reacts to stylus button press events or not.
+     *
+     * @return true if the view is stylus button pressable, false otherwise
+     * @see #setStylusButtonPressable(boolean)
+     * @attr ref android.R.styleable#View_stylusButtonPressable
+     */
+    public boolean isStylusButtonPressable() {
+        return (mViewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE;
+    }
+
+    /**
+     * Enables or disables stylus button press events for this view. When a view is stylus button
+     * pressable it reacts to the user touching the screen with a stylus and pressing the first
+     * stylus button. This event can launch the listener.
+     *
+     * @param stylusButtonPressable true to make the view react to a stylus button press, false
+     *            otherwise
+     * @see #isStylusButtonPressable()
+     * @attr ref android.R.styleable#View_stylusButtonPressable
+     */
+    public void setStylusButtonPressable(boolean stylusButtonPressable) {
+        setFlags(stylusButtonPressable ? STYLUS_BUTTON_PRESSABLE : 0, STYLUS_BUTTON_PRESSABLE);
+    }
+
+    /**
      * Sets the pressed state for this view and provides a touch coordinate for
      * animation hinting.
      *
@@ -7856,7 +7979,8 @@
     public void addTouchables(ArrayList<View> views) {
         final int viewFlags = mViewFlags;
 
-        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
+        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
+                || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE)
                 && (viewFlags & ENABLED_MASK) == ENABLED) {
             views.add(this);
         }
@@ -8571,6 +8695,12 @@
                     return requestRectangleOnScreen(r, true);
                 }
             } break;
+            case R.id.accessibilityActionStylusButtonPress: {
+                if (isStylusButtonPressable()) {
+                    performStylusButtonPress();
+                    return true;
+                }
+            } break;
         }
         return false;
     }
@@ -9728,7 +9858,8 @@
         }
 
         return (viewFlags & CLICKABLE) == CLICKABLE
-                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
+                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
+                || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE;
     }
 
     /**
@@ -9811,15 +9942,17 @@
         final float x = event.getX();
         final float y = event.getY();
         final int viewFlags = mViewFlags;
+        final int action = event.getAction();
 
         if ((viewFlags & ENABLED_MASK) == DISABLED) {
-            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
+            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                 setPressed(false);
             }
             // A disabled view that is clickable still consumes the touch
             // events, it just doesn't respond to them.
-            return (((viewFlags & CLICKABLE) == CLICKABLE ||
-                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
+            return (((viewFlags & CLICKABLE) == CLICKABLE
+                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
+                    || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE);
         }
 
         if (mTouchDelegate != null) {
@@ -9829,9 +9962,14 @@
         }
 
         if (((viewFlags & CLICKABLE) == CLICKABLE ||
-                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
-            switch (event.getAction()) {
+                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
+                (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE) {
+            switch (action) {
                 case MotionEvent.ACTION_UP:
+                    if (mInStylusButtonPress) {
+                        mInStylusButtonPress = false;
+                        mHasPerformedLongPress = false;
+                    }
                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
                         // take focus if we don't have it already and we should in
@@ -9885,6 +10023,11 @@
 
                 case MotionEvent.ACTION_DOWN:
                     mHasPerformedLongPress = false;
+                    mInStylusButtonPress = false;
+
+                    if (performStylusActionOnButtonPress(event)) {
+                        break;
+                    }
 
                     if (performButtonActionOnTouchDown(event)) {
                         break;
@@ -9914,6 +10057,10 @@
                     setPressed(false);
                     removeTapCallback();
                     removeLongPressCallback();
+                    if (mInStylusButtonPress) {
+                        mInStylusButtonPress = false;
+                        mHasPerformedLongPress = false;
+                    }
                     break;
 
                 case MotionEvent.ACTION_MOVE:
@@ -9929,6 +10076,9 @@
 
                             setPressed(false);
                         }
+                    } else if (performStylusActionOnButtonPress(event)) {
+                        // Check for stylus button press if we're within the view.
+                        break;
                     }
                     break;
             }
@@ -10216,7 +10366,8 @@
 
         if (accessibilityEnabled) {
             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
-                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
+                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
+                    || (changed & STYLUS_BUTTON_PRESSABLE) != 0) {
                 if (oldIncludeForAccessibility != includeForAccessibility()) {
                     notifySubtreeAccessibilityStateChangedIfNeeded();
                 } else {
@@ -20782,6 +20933,20 @@
     }
 
     /**
+     * Interface definition for a callback to be invoked when a view is touched with a stylus while
+     * the stylus button is pressed.
+     */
+    public interface OnStylusButtonPressListener {
+        /**
+         * Called when a view is touched with a stylus while the stylus button is pressed.
+         *
+         * @param v The view that was touched.
+         * @return true if the callback consumed the stylus button press, false otherwise.
+         */
+        boolean onStylusButtonPress(View v);
+    }
+
+    /**
      * Interface definition for a callback to be invoked when the context menu
      * for this view is being built.
      */
diff --git a/core/java/android/view/ViewAssistStructure.java b/core/java/android/view/ViewAssistStructure.java
index 346b8ec..fccfbb8 100644
--- a/core/java/android/view/ViewAssistStructure.java
+++ b/core/java/android/view/ViewAssistStructure.java
@@ -40,6 +40,8 @@
 
     public abstract void setLongClickable(boolean state);
 
+    public abstract void setStylusButtonPressable(boolean state);
+
     public abstract void setFocusable(boolean state);
 
     public abstract void setFocused(boolean state);
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 417e22c..b0dbeca 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -684,6 +684,11 @@
     public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
 
     /**
+     * Represents the event of a stylus button press on a {@link android.view.View}.
+     */
+    public static final int TYPE_VIEW_STYLUS_BUTTON_PRESSED = 0x00800000;
+
+    /**
      * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
      * The type of change is not defined.
      */
@@ -731,6 +736,7 @@
      * @see #TYPE_TOUCH_INTERACTION_START
      * @see #TYPE_TOUCH_INTERACTION_END
      * @see #TYPE_WINDOWS_CHANGED
+     * @see #TYPE_VIEW_STYLUS_BUTTON_PRESSED
      */
     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
 
@@ -1396,6 +1402,14 @@
                     builder.append("TYPE_WINDOWS_CHANGED");
                     eventTypeCount++;
                 } break;
+                case TYPE_VIEW_STYLUS_BUTTON_PRESSED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_STYLUS_BUTTON_PRESSED");
+                    eventTypeCount++;
+                }
+                    break;
             }
         }
         if (eventTypeCount > 1) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 0736ed8..bf4b7ae 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -520,6 +520,8 @@
 
     private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
 
+    private static final int BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE = 0x00020000;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -1930,6 +1932,30 @@
     }
 
     /**
+     * Gets whether this node is stylus button pressable.
+     *
+     * @return True if the node is stylus button pressable.
+     */
+    public boolean isStylusButtonPressable() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE);
+    }
+
+    /**
+     * Sets whether this node is stylus button pressable.
+     * <p>
+     * <strong>Note:</strong> Cannot be called from an
+     * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
+     * before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param stylusButtonPressable True if the node is stylus button pressable.
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setStylusButtonPressable(boolean stylusButtonPressable) {
+        setBooleanProperty(BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE, stylusButtonPressable);
+    }
+
+    /**
      * Gets the node's live region mode.
      * <p>
      * A live region is a node that contains information that is important for
@@ -3117,6 +3143,7 @@
         builder.append("; selected: ").append(isSelected());
         builder.append("; clickable: ").append(isClickable());
         builder.append("; longClickable: ").append(isLongClickable());
+        builder.append("; stylusButtonPressable: ").append(isStylusButtonPressable());
         builder.append("; enabled: ").append(isEnabled());
         builder.append("; password: ").append(isPassword());
         builder.append("; scrollable: ").append(isScrollable());
@@ -3472,6 +3499,12 @@
         public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
                 new AccessibilityAction(R.id.accessibilityActionScrollToPosition, null);
 
+        /**
+         * Action that stylus button presses the node.
+         */
+        public static final AccessibilityAction ACTION_STYLUS_BUTTON_PRESS =
+                new AccessibilityAction(R.id.accessibilityActionStylusButtonPress, null);
+
         private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
         static {
             sStandardActions.add(ACTION_FOCUS);
@@ -3498,6 +3531,7 @@
             sStandardActions.add(ACTION_SET_TEXT);
             sStandardActions.add(ACTION_SHOW_ON_SCREEN);
             sStandardActions.add(ACTION_SCROLL_TO_POSITION);
+            sStandardActions.add(ACTION_STYLUS_BUTTON_PRESS);
         }
 
         private final int mActionId;
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index 191662c..6d4e058 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -216,6 +216,8 @@
         if (mVelocityTracker == null) {
             return super.onTouchEvent(ev);
         }
+        // offset because the view is translated during swipe
+        ev.offsetLocation(mTranslationX, 0);
         switch (ev.getActionMasked()) {
             case MotionEvent.ACTION_UP:
                 updateDismiss(ev);
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 4c4a39d..d4069a1 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -261,7 +261,7 @@
     SkBitmap* outputBitmap = NULL;
     unsigned int existingBufferSize = 0;
     if (javaBitmap != NULL) {
-        outputBitmap = GraphicsJNI::getSkBitmap(env, javaBitmap);
+        outputBitmap = GraphicsJNI::getSkBitmapDeprecated(env, javaBitmap);
         if (outputBitmap->isImmutable()) {
             ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
             javaBitmap = NULL;
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 3525d07..aeea808 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -217,7 +217,7 @@
 
     if (tileBitmap != NULL) {
         // Re-use bitmap.
-        bitmap = GraphicsJNI::getSkBitmap(env, tileBitmap);
+        bitmap = GraphicsJNI::getSkBitmapDeprecated(env, tileBitmap);
     }
     if (bitmap == NULL) {
         bitmap = new SkBitmap;
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 44037dd..f793df1 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -338,7 +338,7 @@
     return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
 }
 
-SkBitmap* GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap) {
+SkBitmap* GraphicsJNI::getSkBitmapDeprecated(JNIEnv* env, jobject bitmap) {
     SkASSERT(env);
     SkASSERT(bitmap);
     SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
@@ -348,6 +348,19 @@
     return b;
 }
 
+void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
+    // TODO: We have to copy from the existing bitmap due to rowBytes not
+    // being updated on the SkPixelRef at reconfigure time. This is a short term
+    // problem that will be fixed with the specialized wrapper
+    *outBitmap = *getSkBitmapDeprecated(env, bitmap);
+}
+
+SkPixelRef* GraphicsJNI::getSkPixelRef(JNIEnv* env, jobject bitmap) {
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_skBitmapPtr);
+    SkBitmap* b = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    return b->pixelRef();
+}
+
 SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) {
     SkASSERT(env);
     if (NULL == jconfig) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index d73507e..8eb43f8 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -49,7 +49,9 @@
     static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
 
     static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
-    static SkBitmap* getSkBitmap(JNIEnv*, jobject bitmap);
+    static SkBitmap* getSkBitmapDeprecated(JNIEnv*, jobject bitmap);
+    static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
+    static SkPixelRef* getSkPixelRef(JNIEnv*, jobject bitmap);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
 
     // Given the 'native' long held by the Rasterizer.java object, return a
diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp
index fc98cf9..876bea4 100644
--- a/core/jni/android/graphics/pdf/PdfRenderer.cpp
+++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp
@@ -243,19 +243,21 @@
 }
 
 static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr,
-        jlong bitmapPtr, jint destLeft, jint destTop, jint destRight, jint destBottom,
+        jobject jbitmap, jint destLeft, jint destTop, jint destRight, jint destBottom,
         jlong matrixPtr, jint renderMode) {
 
     FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr);
-    SkBitmap* skBitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
     SkMatrix* skMatrix = reinterpret_cast<SkMatrix*>(matrixPtr);
 
-    skBitmap->lockPixels();
+    SkBitmap skBitmap;
+    GraphicsJNI::getSkBitmap(env, jbitmap, &skBitmap);
 
-    const int stride = skBitmap->width() * 4;
+    SkAutoLockPixels alp(skBitmap);
 
-    FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap->width(), skBitmap->height(),
-            FPDFBitmap_BGRA, skBitmap->getPixels(), stride);
+    const int stride = skBitmap.width() * 4;
+
+    FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(),
+            FPDFBitmap_BGRA, skBitmap.getPixels(), stride);
 
     if (!bitmap) {
         ALOGE("Erorr creating bitmap");
@@ -278,8 +280,7 @@
     renderPageBitmap(bitmap, page, destLeft, destTop, destRight,
             destBottom, skMatrix, renderFlags);
 
-    skBitmap->notifyPixelsChanged();
-    skBitmap->unlockPixels();
+    skBitmap.notifyPixelsChanged();
 }
 
 static JNINativeMethod gPdfRenderer_Methods[] = {
@@ -287,7 +288,7 @@
     {"nativeClose", "(J)V", (void*) nativeClose},
     {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
     {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting},
-    {"nativeRenderPage", "(JJJIIIIJI)V", (void*) nativeRenderPage},
+    {"nativeRenderPage", "(JJLandroid/graphics/Bitmap;IIIIJI)V", (void*) nativeRenderPage},
     {"nativeOpenPageAndGetSize", "(JILandroid/graphics/Point;)J", (void*) nativeOpenPageAndGetSize},
     {"nativeClosePage", "(J)V", (void*) nativeClosePage}
 };
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 5c2d0d0..bce2b33 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -618,23 +618,25 @@
 static jint util_getInternalFormat(JNIEnv *env, jclass clazz,
         jobject jbitmap)
 {
-    SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
-    return getInternalFormat(nativeBitmap->colorType());
+    SkBitmap nativeBitmap;
+    GraphicsJNI::getSkBitmap(env, jbitmap, &nativeBitmap);
+    return getInternalFormat(nativeBitmap.colorType());
 }
 
 static jint util_getType(JNIEnv *env, jclass clazz,
         jobject jbitmap)
 {
-    SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
-    return getType(nativeBitmap->colorType());
+    SkBitmap nativeBitmap;
+    GraphicsJNI::getSkBitmap(env, jbitmap, &nativeBitmap);
+    return getType(nativeBitmap.colorType());
 }
 
 static jint util_texImage2D(JNIEnv *env, jclass clazz,
         jint target, jint level, jint internalformat,
         jobject jbitmap, jint type, jint border)
 {
-    SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
-    const SkBitmap& bitmap(*nativeBitmap);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
     SkColorType colorType = bitmap.colorType();
     if (internalformat < 0) {
         internalformat = getInternalFormat(colorType);
@@ -680,8 +682,8 @@
         jint target, jint level, jint xoffset, jint yoffset,
         jobject jbitmap, jint format, jint type)
 {
-    SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
-    const SkBitmap& bitmap(*nativeBitmap);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
     SkColorType colorType = bitmap.colorType();
     if (format < 0) {
         format = getInternalFormat(colorType);
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 3ae829b..5d08532 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -42,7 +42,7 @@
 static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
     SkBitmap* bitmap = nullptr;
     if (jbitmap != NULL) {
-        bitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
+        bitmap = GraphicsJNI::getSkBitmapDeprecated(env, jbitmap);
     }
     return reinterpret_cast<jlong>(Canvas::create_canvas(
             bitmap ? *bitmap : SkBitmap()));
@@ -53,7 +53,7 @@
 static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
     SkBitmap* bitmap = nullptr;
     if (jbitmap != NULL) {
-        bitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
+        bitmap = GraphicsJNI::getSkBitmapDeprecated(env, jbitmap);
     }
     get_canvas(canvasHandle)->setBitmap(bitmap ? *bitmap : SkBitmap());
 }
diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp
index f6d9a1a..d04adbf 100644
--- a/core/jni/android_view_PointerIcon.cpp
+++ b/core/jni/android_view_PointerIcon.cpp
@@ -80,10 +80,7 @@
 
     jobject bitmapObj = env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmap);
     if (bitmapObj) {
-        SkBitmap* bitmap = GraphicsJNI::getSkBitmap(env, bitmapObj);
-        if (bitmap) {
-            outPointerIcon->bitmap = *bitmap; // use a shared pixel ref
-        }
+        GraphicsJNI::getSkBitmap(env, bitmapObj, &(outPointerIcon->bitmap));
         env->DeleteLocalRef(bitmapObj);
     }
 
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 7080e2a..baeb7dd 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -277,8 +277,9 @@
     EGLConfig  cnf = getConfig(_env, config);
     jint* base = 0;
 
-    SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(_env, native_pixmap);
-    SkPixelRef* ref = nativeBitmap ? nativeBitmap->pixelRef() : 0;
+    SkBitmap nativeBitmap;
+    GraphicsJNI::getSkBitmap(_env, native_pixmap, &nativeBitmap);
+    SkPixelRef* ref = nativeBitmap.pixelRef();
     if (ref == NULL) {
         jniThrowException(_env, "java/lang/IllegalArgumentException", "Bitmap has no PixelRef");
         return;
@@ -289,10 +290,10 @@
 
     egl_native_pixmap_t pixmap;
     pixmap.version = sizeof(pixmap);
-    pixmap.width  = nativeBitmap->width();
-    pixmap.height = nativeBitmap->height();
-    pixmap.stride = nativeBitmap->rowBytes() / nativeBitmap->bytesPerPixel();
-    pixmap.format = convertPixelFormat(nativeBitmap->colorType());
+    pixmap.width  = nativeBitmap.width();
+    pixmap.height = nativeBitmap.height();
+    pixmap.stride = nativeBitmap.rowBytes() / nativeBitmap.bytesPerPixel();
+    pixmap.format = convertPixelFormat(nativeBitmap.colorType());
     pixmap.data   = (uint8_t*)ref->pixels();
 
     base = beginNativeAttribList(_env, attrib_list);
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e993ceb..52b31b2 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2329,6 +2329,9 @@
         <!-- Defines whether this view reacts to long click events. -->
         <attr name="longClickable" format="boolean" />
 
+        <!--  Defines whether this view reacts to stylus button press events. -->
+        <attr name="stylusButtonPressable" format="boolean" />
+
         <!-- If false, no state will be saved for this view when it is being
              frozen. The default is true, allowing the view to be saved
              (however it also must have an ID assigned to it for its
@@ -2722,12 +2725,11 @@
         <attr name="value" />
     </declare-styleable>
 
-    <!-- Attributes that can be assigned to an &lt;include&gt; tag. -->
+    <!-- Attributes that can be assigned to an &lt;include&gt; tag.
+         @hide -->
     <declare-styleable name="Include">
         <attr name="id" />
         <attr name="visibility" />
-        <attr name="layout_width" />
-        <attr name="layout_height" />
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -3076,6 +3078,8 @@
             <flag name="typeTouchInteractionEnd" value="0x00200000" />
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED} events. -->
             <flag name="typeWindowsChanged" value="0x00400000" />
+            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_STYLUS_BUTTON_PRESSED} events. -->
+            <flag name="typeStylusButtonPressed" value="0x00800000" />
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. -->
             <flag name="typeAllMask" value="0xffffffff" />
         </attr>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6f60188..0b8b280 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -771,6 +771,14 @@
         <item>10</item>
     </integer-array>
 
+    <!-- Vibrator pattern for feedback about a stylus button press -->
+    <integer-array name="config_stylusButtonPressVibePattern">
+        <item>0</item>
+        <item>1</item>
+        <item>20</item>
+        <item>21</item>
+    </integer-array>
+
     <bool name="config_use_strict_phone_number_comparation">false</bool>
 
     <!-- Display low battery warning when battery level dips to this value.
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index bdc8d9f..4b8bd0f 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -100,4 +100,7 @@
 
   <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_TO_POSITION}. -->
   <item type="id" name="accessibilityActionScrollToPosition" />
+
+  <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_STYLUS_BUTTON_PRESS}. -->
+  <item type="id" name="accessibilityActionStylusButtonPress" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index dd4c134..cf21a1c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2652,6 +2652,7 @@
   <public type="id" name="accessibilityActionShowOnScreen" />
   <public type="id" name="accessibilityActionScrollToPosition" />
   <public type="id" name="shareText" />
+  <public type="id" name="accessibilityActionStylusButtonPress" />
 
   <public type="attr" name="allowUndo" />
   <public type="attr" name="colorBackgroundFloating" />
@@ -2678,4 +2679,5 @@
   <public type="attr" name="dynamicResources" />
 
   <public type="attr" name="assistBlocked" />
+  <public type="attr" name="stylusButtonPressable" />
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 625f003..50d2f80 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1442,6 +1442,7 @@
   <java-symbol type="array" name="config_longPressVibePattern" />
   <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
   <java-symbol type="array" name="config_safeModeEnabledVibePattern" />
+  <java-symbol type="array" name="config_stylusButtonPressVibePattern" />
   <java-symbol type="array" name="config_virtualKeyVibePattern" />
   <java-symbol type="attr" name="actionModePopupWindowStyle" />
   <java-symbol type="attr" name="dialogCustomTitleDecorLayout" />
diff --git a/docs/html/images/tools/studio-add-icon.png b/docs/html/images/tools/studio-add-icon.png
new file mode 100644
index 0000000..3ff49f6
--- /dev/null
+++ b/docs/html/images/tools/studio-add-icon.png
Binary files differ
diff --git a/docs/html/images/tools/studio-debug-settings-icon.png b/docs/html/images/tools/studio-debug-settings-icon.png
new file mode 100644
index 0000000..ee9c7a1
--- /dev/null
+++ b/docs/html/images/tools/studio-debug-settings-icon.png
Binary files differ
diff --git a/docs/html/images/tools/studio-inspections-config.png b/docs/html/images/tools/studio-inspections-config.png
index e41afa1..15a5a5b 100644
--- a/docs/html/images/tools/studio-inspections-config.png
+++ b/docs/html/images/tools/studio-inspections-config.png
Binary files differ
diff --git a/docs/html/images/tools/studio-memory-monitor.png b/docs/html/images/tools/studio-memory-monitor.png
index 796daf0..58147b7 100644
--- a/docs/html/images/tools/studio-memory-monitor.png
+++ b/docs/html/images/tools/studio-memory-monitor.png
Binary files differ
diff --git a/docs/html/images/tools/studio-memory-monitor2x.png b/docs/html/images/tools/studio-memory-monitor2x.png
new file mode 100644
index 0000000..7c3d6c4
--- /dev/null
+++ b/docs/html/images/tools/studio-memory-monitor2x.png
Binary files differ
diff --git a/docs/html/sdk/installing/studio-tips.jd b/docs/html/sdk/installing/studio-tips.jd
index c3edff6..4e732f0 100644
--- a/docs/html/sdk/installing/studio-tips.jd
+++ b/docs/html/sdk/installing/studio-tips.jd
@@ -22,8 +22,8 @@
      <h2>Smart Rendering</h2>
      <p>With smart rendering, Android Studio displays links for quick fixes to rendering errors.
      For example, if you add a button to the layout without specifying the <em>width</em> and
-     <em>height</em> atttributes, Android Studio displays the rendering message <em>Automatically
-     add all missing attributs</em>. Clicking the message adds the missing attributes to the layout.</p>
+     <em>height</em> attributes, Android Studio displays the rendering message <em>Automatically
+     add all missing attributes</em>. Clicking the message adds the missing attributes to the layout.</p>
 
 
      <h2> Bitmap rendering in the debugger</h2>
@@ -41,7 +41,6 @@
      <p class="img-caption"><strong>Figure 14.</strong> Filter Build Messages</p>
 
 
-
     <h2>Hierarchical parent setting</h2>
     <p>The activity parent can now be set in the Activity Wizard when creating a new
     activity. Setting a <em>hierarchal parent</em> sets the {@code Up} button to automatically
@@ -69,7 +68,47 @@
     with a layout hierarchy and a list of properties for each view in the layout.</p>
 
 
-     <h2 id="intellij">Working with IntelliJ</h3>
+   <h3>Annotations</h3>
+   <p>Android Studio provides coding assistance for using annotations from the
+   {@link android.support.annotation Support-Annotations} library, part of the
+   Support Repository. Adding a dependency for this library enables you to decorate your code with
+   annotations to help catch bugs, such as null pointer exceptions and resource type conflicts.
+   You can also create enumerated annotations to, for example, check that a passed parameter value
+   matches a value from a defined set of constants. For more information, see
+   <a href="{@docRoot}tools/debugging/annotations.html#annotations">Improving Code Inspection with
+   Annotations</a>. </p>
+
+
+   <h3>Java class decompiling</h3>
+   <p>Android Studio allows you to look at what’s inside Java libraries when you don’t have access
+   to the source code. </p>
+
+   <p>The decompiler is built into Android Studio for easy access. To use this feature, right-click
+   a class, method, or field from a library for which you do not have source file access and select
+   <strong>decompile</strong>.</p> The decompiled source code appears. </p>
+
+   <p>To adjust the Java decompiler settings, select
+   <strong>File > Settings > Other Settings > Java Decompiler</strong>. </p>
+
+
+   <h3>Debugging and performance enhancements</h3>
+   <p>Android Studio offers debugging and performance enhancements such as:</p>
+   <ul>
+    <li>Auto detect an expanded set of code styles. To modify the current code style, choose
+      <strong>File &gt; Settings &gt; Code Styles</strong>.  </li>
+    <li>Support for high density (Retina) displays on Windows and Linux.  </li>
+    <li>Scratch files for quick prototyping without creating any project files.
+      <p>Choose <strong>Tools &gt; New Scratch File</strong> to open a scratch file to quickly
+      build and run code prototypes. Together with Android Studio coding assistance, scratch
+      files allow you to quickly run and debug code updates with the support of all file operations.
+      By embedding code created with scripting languages, you can run your code from within the
+      scratch file.</p> 
+    </li>
+  </ul>
+
+
+
+<h2 id="intellij">Working with IntelliJ-based Coding Practices</h2>
 
      <p>This section list just a few of the code editing
      practices you should consider using when creating Android Studio apps. </p>
@@ -78,8 +117,6 @@
      is based), refer to the
      <a href="http://www.jetbrains.com/idea/documentation/index.jsp">IntelliJ IDEA documentation</a>.</p>
 
-
-
      <h3><em>Alt + Enter</em> key binding</h3>
      <p>For quick fixes to coding errors, the IntelliJ powered IDE implements the <em>Alt + Enter</em>
      key binding to fix errors (missing imports, variable assignments, missing references, etc) when
@@ -108,18 +145,16 @@
     of a string as not null.</p>
 
 
-
     <h3>Injecting languages</h3>
     <p>With language injection, the Android Studio IDE allows you to work with islands of different
     languages embedded in the source code. This extends the syntax, error highlighting and coding
     assistance to the embedded language. This can be especially useful for checking regular expression
-    values inline, and validating XML and SQL statments.</p>
-
+    values inline, and validating XML and SQL statements.</p>
 
     <h3>Code folding</h3>
     <p>This allows you to selectively hide and display sections of the code for readability. For
     example, resource expressions or code for a nested class can be folded or hidden in to one line
-    to make the outer class structure easier to read. The inner clas can be later expanded for
+    to make the outer class structure easier to read. The inner class can be later expanded for
     updates. </p>
 
 
@@ -140,6 +175,7 @@
     resolved values for the various attributes that are pulled in.</p>
 
 
+
      <h3>New Allocation Tracker integration in the Android/DDMS window</h3>
      <p>You can now inspect theme attributes using <strong> View > Quick Documentation
      </strong> <code>F1</code>, see the theme inheritance hierarchy, and resolved values for the
diff --git a/docs/html/tools/building/building-cmdline.jd b/docs/html/tools/building/building-cmdline.jd
index ec00b50..33798a5 100644
--- a/docs/html/tools/building/building-cmdline.jd
+++ b/docs/html/tools/building/building-cmdline.jd
@@ -34,9 +34,9 @@
     </div>
   </div>
 
-  <p>By default, there are two build types to build your application using the gradle.build settings:
+  <p>By default, there are two build types to build your application using the Gradle build settings:
   one for debugging your application &mdash; <em>debug</em> &mdash; and one for building your
-  final package for release &mdash; <em>release mode</em>. Regardless of which way you build type
+  final package for release &mdash; <em>release mode</em>. Regardless of which build type
   your modules use, the app must be signed before it can install on an emulator or device&mdash;with
   a debug key when building in debug mode and with your own private key when building in release mode.</p>
 
@@ -48,23 +48,24 @@
   development device. You cannot distribute an application that is signed with a debug key.
   When you build using the release build type, the .apk file is <em>unsigned</em>, so you
   must manually sign it with your own private key, using Keytool and Jarsigner settings in the
-  module's gradle.build file.</p>
+  module's <code>build.gradle</code> file.</p>
 
   <p>It's important that you read and understand <a href=
   "{@docRoot}tools/publishing/app-signing.html">Signing Your Applications</a>, particularly once
   you're ready to release your application and share it with end-users. That document describes the
-  procedure for generating a private key and then using it to sign your .apk file. If you're just
+  procedure for generating a private key and then using it to sign your APK file. If you're just
   getting started, however, you can quickly run your applications on an emulator or your own
   development device by building in debug mode.</p>
 
   <p>If you don't have <a href="http://www.gradle.org/">Gradle</a>, you can obtain it from the <a href="http://gradle.org/">Gradle
-  home page</a>. Install it and make sure it is in your executable PATH. Before calling Ant, you
+  home page</a>. Install it and make sure it is in your executable PATH. Before calling Gradle, you
   need to declare the JAVA_HOME environment variable to specify the path to where the JDK is
   installed.</p>
 
-  <p class="note"><strong>Note:</strong> When installing JDK on Windows, the default is to install
-  in the "Program Files" directory. This location will cause <code>ant</code> to fail, because of
-  the space. To fix the problem, you can specify the JAVA_HOME variable like this:
+  <p class="note"><strong>Note:</strong> When using <code>ant</code> and installing JDK on Windows,
+  the default is to install in the "Program Files" directory. This location will cause
+  <code>ant</code> to fail, because of the space. To fix the problem, you can specify the JAVA_HOME
+  variable like this:
   <pre>set JAVA_HOME=c:\Progra~1\Java\&lt;jdkdir&gt;</pre>
 
   <p>The easiest solution, however, is to install JDK in a non-space directory, for example:</p>
diff --git a/docs/html/tools/debugging/annotations.jd b/docs/html/tools/debugging/annotations.jd
new file mode 100644
index 0000000..fe9f9cc
--- /dev/null
+++ b/docs/html/tools/debugging/annotations.jd
@@ -0,0 +1,241 @@
+page.title=Improving Code Inspection with Annotations
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+    <h2>In this document</h2>
+    <ol>
+      <li><a href="#adding-nullness">Adding Nullness Annotations</a></li>
+      <li><a href="#res-annotations">Adding Resource Annotation</a></li>
+      <li><a href="#enum-annotations">Creating Enumerated Annotations</a></li>
+    </ol>
+
+  <h2>See also</h2>
+  <ol>
+     <li><a href="{@docRoot}tools/help/lint.html">lint (reference)</a></li>
+     <li><a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a></li>
+     <li><a href="{@docRoot}tools/studio/index.html#annotations">Annotations in Android Studio</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>Using code inspections tools such as <a href="{@docRoot}tools/help/lint.html">lint</a> can help
+you find problems and improve your code, but inspection tools can only infer so much. Android
+resource ids, for example, use an {@code int} to identify strings, graphics, colors and other
+resource types, so inspection tools cannot tell when you have specified a string resource where
+you should have specified a color. This situation means that your app may render incorrectly or
+fail to run at all, even if you use code inspection. </p>
+
+<p>Annotations allow you to provide hints to code inspections tools like {@code lint}, to help
+detect these, more subtle code problems. They are added as metadata tags that you attach to
+variables, parameters, and return values to inspect method return values, passed parameters, and
+local variables and fields. When used with code inspections tools, annotations can help you detect
+problems, such as null pointer exceptions and resource type
+conflicts. </p>
+
+<p>For more information on enabling <a href="{@docRoot}tools/help/lint.html">lint</a> inspections
+and running <a href="{@docRoot}tools/help/lint.html">lint</a>,
+see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
+
+<p>Android supports a variety of annotations for insertion in the methods, parameters, and return
+values in your code, for example:</p>
+
+<dl>
+    <dt>{@link android.support.annotation.Nullable @Nullable}</dt>
+    <dd>Can be null.</dd>
+
+    <dt>{@link android.support.annotation.NonNull @NonNull}</dt>
+    <dd>Cannot be null.</dd>
+
+    <dt>{@link android.support.annotation.StringRes @StringRes}</dt>
+    <dd>References a <a href="{@docRoot}reference/android/R.string.html"><code>R.string</code></a>
+    resource.</dd>
+
+    <dt>{@link android.support.annotation.DrawableRes @DrawableRes}</dt>
+    <dd>References a
+    <a href="{@docRoot}guide/topics/resources/drawable-resource.html"><code>Drawable</code></a>
+    resource. </dd>
+
+    <dt>{@link android.support.annotation.ColorRes @ColorRes}</dt>
+    <dd>References a <a href="{@docRoot}reference/android/graphics/Color.html"><code>Color</code></a>
+    resource. </dd>
+
+    <dt>{@link android.support.annotation.InterpolatorRes @InterpolatorRes}</dt>
+    <dd>References a
+    <a href="{@docRoot}reference/android/view/animation/Interpolator.html"><code>Interpolator</code></a>
+    resource. </dd>
+
+    <dt>{@link android.support.annotation.AnyRes @AnyRes}</dt>
+    <dd>References any type of <a href="{@docRoot}reference/android/R.html"><code>R.</code></a>
+    resource. </dd>
+  </dl>
+
+<p>For a complete list of the supported annotations, either examine the contents of the
+{@link android.support.annotation Support-Annotations} library or use the
+auto-complete feature to display the available options for the <code>import
+android.support.annotation.</code> statement. The
+<a href="{@docRoot}tools/help/sdk-manager.html"> SDK Manager</a> packages the
+{@link android.support.annotation Support-Annotations} library in the Android Support Repository
+for use with Android Studio and in the Android
+<a href="{@docRoot}tools/support-library/index.html">Support Library</a> for use with other Android
+development tools.</p>
+
+
+<p>To add annotations to your code, first add a dependency to the
+{@link android.support.annotation Support-Annotations} library. In Android Studio,
+add the dependency to your <code>build.gradle</code> file. </p>
+
+<pre>
+dependencies {
+    compile 'com.android.support:support-annotations:22.0.0'
+}
+</pre>
+
+
+<p>The {@link android.support.annotation Support-Annotations} library is decorated with the
+supported annotations so using this library's methods and resources automatically checks the code
+for potential problems.</p>
+
+<p>If you include annotations in a library and use the
+<a href="{@docRoot}tools/building/plugin-for-gradle.html"><code>Android Plugin for Gradle</code></a>
+to build an Android ARchive (AAR) artifact of that library, the annotations are included as part
+of the artifact in XML format in the <code>annotations.zip</code> file. </p>
+
+<p>To start a code inspection from Android Studio, which includes validating annotations and
+automatic <a href="{@docRoot}tools/help/lint.html">lint</a> checking, select
+<strong>Analyze > Inspect Code</strong> from the menu options. Android Studio displays conflict
+messages throughout the code to indication annotation conflicts and suggest possible
+resolutions.</p>
+
+
+<h2 id="adding-nullness">Adding Nullness Annotations</h2>
+<p>Add {@link android.support.annotation.Nullable @Nullable} and
+{@link android.support.annotation.NonNull @NonNull} annotations to check
+the nullness of a given variable, parameter, or return value. For example, if a local variable
+that contains a null value is passed as a parameter to a method with the
+{@link android.support.annotation.NonNull @NonNull} annotation
+attached to that parameter, building the code generates a warning indicating a non-null conflict. </p>
+
+<p>This example attaches the {@link android.support.annotation.NonNull @NonNull} annotation to
+the <code>context</code> and <code>attrs</code> parameters to check that the passed parameter
+values are not null. </p>
+
+<pre>
+import android.support.annotation.NonNull;
+...
+
+    /** Add support for inflating the &lt;fragment&gt; tag. */
+    &#64;NonNull
+    &#64;Override
+    public View onCreateView(String name, &#64;NonNull Context context,
+      &#64;NonNull AttributeSet attrs) {
+      ...
+      }
+...
+</pre>
+
+<p class="note"><strong>Note:</strong> Android Studio supports running a nullability analysis to
+automatically infer and insert nullness annotations in your code. For more information about
+inferring nullability in Android Studio, see
+<a href="{@docRoot}tools/studio/index.html#annotations">Annotations in Android Studio</a>. </p>
+
+
+<h2 id="res-annotations">Adding Resource Annotations</h2>
+<p>Add {@link android.support.annotation.StringRes @StringRes} annotations to check that
+a resource parameter contains a
+<a href="{@docRoot}reference/android/R.string.html"><code>R.string</code></a>
+reference. During code inspection, the annotation generates a warning if a <code>R.string</code>
+reference is not passed in the parameter.</p>
+
+<p>Validating resource types can be useful as Android references to
+<a href="{@docRoot}guide/topics/resources/drawable-resource.html"><code>Drawables</code></a> and
+<a href="{@docRoot}reference/android/R.string.html"><code>R.string</code></a> resources are both
+passed as integers. Code that expects a parameter to reference a <code>Drawable</code> can be passed
+the expected reference type of int, but actually reference a <code>R.string</code></a> resource. </p>
+
+<p>This example attaches the {@link android.support.annotation.StringRes @StringRes}
+annotation to the <code>resId</code> parameter to validate that it is really a string resource.  </p>
+
+<pre>
+import android.support.annotation.StringRes;
+...
+    public abstract void setTitle(&#64;StringRes int resId);
+    ...
+</pre>
+
+
+<p>Annotations for the other resource types, such as
+{@link android.support.annotation.DrawableRes @DrawableRes},
+{@link android.support.annotation.ColorRes @ColorRes}, and
+{@link android.support.annotation.InterpolatorRes @InterpolatorRes} can be added using
+the same annotation format and run during the code inspection.  </p>
+
+
+<h2 id="enum-annotations">Creating Enumerated Annotations</h2>
+<p>Use the {@link android.support.annotation.IntDef @IntDef} and
+{@link android.support.annotation.StringDef @StringDef} annotations
+so you can create enumerated annotations of integer and string sets to validate other types of code
+references, such as passing references to a set of constants. </p>
+
+<p>The following example illustrates the steps to create an enumerated annotation that ensures
+a value passed as a method parameter references one of the defined constants.</p>
+
+<pre>
+import android.support.annotation.IntDef;
+...
+public abstract class ActionBar {
+    ...
+    //Define the list of accepted constants
+    &#64;IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
+
+    //Tell the compiler not to store annotation data in the <code>.class</code> file
+    &#64;Retention(RetentionPolicy.SOURCE)
+
+    //Declare the <code>NavigationMode</code> annotation
+    public &#64;interface NavigationMode {}
+
+    //Declare the constants
+    public static final int NAVIGATION_MODE_STANDARD = 0;
+    public static final int NAVIGATION_MODE_LIST = 1;
+    public static final int NAVIGATION_MODE_TABS = 2;
+
+    //Decorate the target methods with the annotation
+    &#64;NavigationMode
+    public abstract int getNavigationMode();
+
+    //Attach the annotation
+    public abstract void setNavigationMode(&#64;NavigationMode int mode);
+
+</pre>
+
+<p>When you build this code, a warning is generated if the <code>mode</code> parameter does
+not reference one of the defined constants (<code>NAVIGATION_MODE_STANDARD</code>,
+<code>NAVIGATION_MODE_LIST</code>, or <code>NAVIGATION_MODE_TABS</code>).</p>
+
+<p>You can also define an annotation with a <code>flag</code> to check if a parameter
+or return value references a valid pattern. This example creates the
+<code>DisplayOptions</code> annotation with a list of valid <code>DISPLAY_</code> constants. </p>
+
+<pre>
+import android.support.annotation.IntDef;
+...
+
+&#64;IntDef(flag=true, value={
+        DISPLAY_USE_LOGO,
+        DISPLAY_SHOW_HOME,
+        DISPLAY_HOME_AS_UP,
+        DISPLAY_SHOW_TITLE,
+        DISPLAY_SHOW_CUSTOM
+})
+&#64;Retention(RetentionPolicy.SOURCE)
+public &#64;interface DisplayOptions {}
+
+...
+</pre>
+
+<p>When you build code with an annotation flag, a warning is generated if the decorated parameter
+or return value does not reference a valid pattern.</p>
+
+
diff --git a/docs/html/tools/debugging/improving-w-lint.jd b/docs/html/tools/debugging/improving-w-lint.jd
index ff94b7f..8f74f46 100644
--- a/docs/html/tools/debugging/improving-w-lint.jd
+++ b/docs/html/tools/debugging/improving-w-lint.jd
@@ -22,6 +22,7 @@
       <h2>See Also</h2>
           <ol>
               <li><a href="{@docRoot}tools/help/lint.html">lint (reference)</a></li>
+              <li><a href="{@docRoot}tools/degugging/annotations.html">Using Android Annotations</a></li>
           </ol>
     </div>
 </div>
diff --git a/docs/html/tools/studio/index.jd b/docs/html/tools/studio/index.jd
index 360b863..95cdb76 100644
--- a/docs/html/tools/studio/index.jd
+++ b/docs/html/tools/studio/index.jd
@@ -18,7 +18,7 @@
 
   <h2>See also</h2>
   <ol>
-    <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA">IntelliJ FAQ on migrating to IntelliJ IDEA</a></li>
+    <li><a class="external-link" href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA">IntelliJ FAQ on migrating to IntelliJ IDEA</a></li>
   </ol>
 
 </div>
@@ -26,8 +26,7 @@
 
 
 <p>Android Studio is the official IDE for Android application development,
-based on <a href="https://www.jetbrains.com/idea/" class="external-link"
-target="_blank">IntelliJ IDEA</a>.
+based on <a class="external-link" href="https://www.jetbrains.com/idea/" target="_blank">IntelliJ IDEA</a>.
 On top of the capabilities you expect from IntelliJ,
 Android Studio offers:</p>
 
@@ -38,10 +37,9 @@
   <li>Rich layout editor with support for drag and drop theme editing</li>
   <li>{@code lint} tools to catch performance, usability, version compatibility, and other problems</li>
   <li>ProGuard and app-signing capabilities</li>
-  <li>Built-in support for <a
-  href="http://developers.google.com/cloud/devtools/android_studio_templates/"
-  class="external-link">Google Cloud Platform</a>, making it easy to integrate Google Cloud
-  Messaging and App Engine</li>
+  <li>Built-in support for
+  <a href="http://developers.google.com/cloud/devtools/android_studio_templates/">Google Cloud Platform</a>,
+  making it easy to integrate Google Cloud Messaging and App Engine</li>
   <li>And much more</li>
 </ul>
 
@@ -62,17 +60,17 @@
 
 <h2 id="project-structure">Project and File Structure</h2>
 
-<h3 id="project-view"><em>Android</em> Project View</h3>
-<p>By default, Android Studio displays your profile files in the <em>Android</em> project view. This
+<h3 id="project-view"><em>Android</em> project view</h3>
+<p>By default, Android Studio displays your project files in the <em>Android</em> project view. This
 view shows a flattened version of your project's structure that provides quick access to the key
 source files of Android projects and helps you work with the
 <a href="{@docRoot}sdk/installing/studio-build.html">Gradle-based build system</a>.
-The Android project view:</p>
+The <em>Android</em> project view:</p>
 
 <ul>
-  <li>Groups the build files for all modules at the top level of the project hierarchy.</li>
   <li>Shows the most important source directories at the top level of the module hierarchy.</li>
-  <li>Groups all the manifest files for each module.</li>
+  <li>Groups the build files for all modules in a common folder.</li>
+  <li>Groups all the manifest files for each module in a common folder.</li>
   <li>Shows resource files from all Gradle source sets.</li>
   <li>Groups resource files for different locales, orientations, and screen types in a single
   group per resource type.</li>
@@ -81,7 +79,7 @@
      <img src="{@docRoot}images/tools/projectview01.png" />
      <p class="img-caption"><strong>Figure 1.</strong> Show the Android project view.</p>
      <img src="{@docRoot}images/tools/studio-projectview_scripts.png"  />
-     <p class="img-caption"><strong>Figure 2.</strong> Project Build Files.</p>
+     <p class="img-caption"><strong>Figure 2.</strong> Show project build Files.</p>
 
 <p>The <em>Android</em> project view shows all the build files at the top level of the project
 hierarchy under <strong>Gradle Scripts</strong>. Each project module appears as a folder at the
@@ -91,18 +89,19 @@
   <li><code>java/</code> - Source files for the module.</li>
   <li><code>manifests/</code> - Manifest files for the module.</li>
   <li><code>res/</code> - Resource files for the module.</li>
+  <li><code>Gradle Scripts/</code> - Gradle build and property files.</li>
 </ul>
 
 <p>For example, <em>Android</em> project view groups all the instances of the
 <code>ic_launcher.png</code> resource for different screen densities under the same element.</p>
 
 <p class="note"><strong>Note:</strong> The project structure on disk differs from this flattened
-representation. To switch to back to the segregated project view, select <strong>Project</strong> from
-the <strong>Project</strong> drop-down. </p>
+representation. To switch to back to the segregated project view, select <strong>Project</strong>
+from the <strong>Project</strong> drop-down. </p>
 
 
-<h3>Android Studio Project and Directory Structure</h3>
-<p>When you use the <em>Project</em> view of a new project in Android Studio, you
+<h3 id="other-views">Other Android Studio views</h3>
+<p>When you use the <em>Project</em> view in Android Studio, you
 should notice that the project structure appears different than you may be used to in Eclipse. Each
 instance of Android Studio contains a project with one or more application modules. Each
 application module folder contains the complete source sets for that module, including
@@ -112,11 +111,28 @@
 specification and the files under {@code src/androidTest} directory for test case creation.
 
     <p>  <img src="{@docRoot}images/tools/studio-project-layout.png" alt="" /></p>
-    <p>  <class="img-caption"><strong>Figure 3.</strong> Android Studio project structure</p>
+    <p>  <class="img-caption"><strong>Figure 3.</strong> View Android Studio <em>Project</em>
+         structure.</p>
+
+<p>You can also customize the view of the project files to focus on specific aspects of your app
+development: </p>
+
+<ul>
+  <li><em>Packages</em> </li>
+  <li><em>Project Files</em> </li>
+  <li><em>Scratches</em> </li>
+  <li><em>Problems</em> </li>
+  <li><em>Production</em> </li>
+  <li><em>Tests</em> </li>
+</ul>
+
+<p>For example, selecting the <strong>Problems</strong> view of your project displays links to the
+source files containing any recognized coding and syntax errors, such as missing a XML element
+closing tag in a layout file.<p>
 
 <p>For more information, see
-<a href="http://confluence.jetbrains.com/display/IntelliJIDEA/Project+Organization"class="external-link">IntelliJ project organization</a> and
-<a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.</p>
+<a class="external-link" href="http://confluence.jetbrains.com/display/IntelliJIDEA/Project+Organization">IntelliJ project organization</a>
+and <a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.</p>
 
 
 
@@ -155,7 +171,7 @@
 <a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>.</p>
 
 
-<h3>Application ID for Package Identification </h3>
+<h3>Application ID for package identification </h3>
 <p>With the Android build system, the <em>applicationId</em> attribute is used to
 uniquely identify application packages for publishing. The application ID is set in the
 <em>android</em> section of the <code>build.gradle</code> file.
@@ -209,7 +225,7 @@
    <pre>
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-   <strong>package="com.example.app"</strong>>
+   <strong>package="com.example.app"</strong>
    </pre>
 
 <p class="note"><strong>Note:</strong> If you have multiple manifests (for example, a product
@@ -242,6 +258,30 @@
 <p>For more information, see <a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs</a>.</p>
 
 
+<h3 id="inline-debug">Inline debugging</h3>
+<p>Use inline debugging to enhance your code walk-throughs in the debugger view
+with inline verification of references, expressions, and variable values. Inline debug information
+includes: </p>
+<ul>
+ <li>Inline variable values</li>
+ <li>Referring objects that reference a selected object </li>
+ <li>Method return values</li>
+ <li>Lambda and operator expressions</li>
+ <li>Tool tip values</li>
+</ul>
+
+<p>To enable inline debugging, in the <em>Debug</em> window click the Settings icon
+<img src="{@docRoot}images/tools/studio-debug-settings-icon.png"/> and select the
+check box for <strong>Show Values In Editor</strong>.</p>
+
+<h3 id="mem-cpu">Memory and CPU monitor</h3>
+<p>Android Studio provides a memory and CPU monitor view so you can more easily monitor your
+app's performance and memory usage to track CPU usage, find deallocated objects, locate memory
+leaks, and track the amount of memory the connected device is using. With your app running on a
+device or emulator, click the <strong>Android</strong> tab in the lower left corner of the
+runtime window to launch the Android runtime window. Click the <strong>Memory</strong> or
+<strong>CPU</strong> tab. </p>
+
 
 <h3 id="memory-monitor">Memory Monitor</h3>
 <p>Android Studio provides a memory monitor view so you can more easily monitor your
@@ -249,18 +289,29 @@
 memory the connected device is using. With your app running on a device or emulator, click the
 <strong>Memory Monitor</strong> tab in the lower right corner to launch the memory monitor. </p>
 
-    <img src="{@docRoot}images/tools/studio-memory-monitor.png" />
-    <p class="img-caption"><strong>Figure 5.</strong> Memory Monitor</p>
+<img src="{@docRoot}images/tools/studio-memory-monitor.png" srcset="{@docRoot}images/tools/studio-memory-monitor_2x.png 2x" width"635" height="171" alt="" />
+    <p class="img-caption"><strong>Figure 4.</strong> Monitor memory and CPU usage.</p>
 
 
+<h3>Data file access</h3>
+<p>The Android SDK tools, such as <a href="{@docRoot}tools/help/systrace.html">Systrace</a>,
+<a href="{@docRoot}tools/help/logcat.html">logcat</a>, and
+<a href="{@docRoot}tools/help/traceview.html">Traceview</a>, generate performance and debugging
+data for detailed app analysis.</p>
 
-<h3>Code Inspections</h3>
-<p>In Android Studio, the configured <a href="{@docRoot}tools/help/lint.html"><code>lint</code></a> and
-other IDE inspections run automatically whenever you compile your program. In addition to the
+<p>To view the available generated data files, click <strong>Captures</strong> in the left
+corner of the runtime window. In the list of the generated files, double-click a file to view
+the data. Right-click any <code>.hprof</code> files to convert them to a standard
+<a href="{@docRoot}tools/help/hprof-conv.html"><code>.hprof</code> </a> file format.</p>
+
+
+<h3>Code inspections</h3>
+<p>In Android Studio, the configured <a href="{@docRoot}tools/help/lint.html"><code>lint</code></a>
+and other IDE inspections run automatically whenever you compile your program. In addition to the
 configured {@code lint} checks, additional
-<a href="https://www.jetbrains.com/idea/help/inspection-basics.html?search=inspection" class="external-link"
-target="_blank">IntelliJ code inspections</a>
-run to streamline code review.</p>
+<a class="external-link" href="https://www.jetbrains.com/idea/help/inspection-basics.html?search=inspection"
+target="_blank">IntelliJ code inspections</a> and annotation validation run to streamline code
+review.</p>
 
 
 <p>Android Studio enables several <code>lint</code> checks
@@ -268,10 +319,10 @@
 <ul>
   <li><code> Cipher.getInstance()</code> is used with safe values</li>
   <li>In custom Views, the associated declare-styleable for the custom view uses the same
-  base name as the class name.</li>
-  <li>Security check for fragment injection.</li>
-  <li>Where ever property assignment no longer works as expected.</li>
-  <li>Gradle plugin version is compatible with the SDK.</li>
+  base name as the class name</li>
+  <li>Security check for fragment injection</li>
+  <li>Where ever property assignment no longer works as expected</li>
+  <li>Gradle plugin version is compatible with the SDK</li>
   <li>Right to left validation </li>
   <li>Required API version</li>
   <li>many others</li>
@@ -301,13 +352,13 @@
 
 
 <p>You can also manage inspection profiles and configure inspections within Android Studio.
-Choose <strong>File &gt; Settings &gt; Project Settings</strong>. The
-<em>Inspection Configuration</em> page appears with the supported inspections.</p>
+Choose <strong>File &gt; Settings &gt; Project Settings</strong> and expand <strong>Editor</strong>.
+The <em>Inspection Configuration</em> page appears with the supported inspections.</p>
 <p><img src="{@docRoot}images/tools/studio-inspections-config.png" alt="" /> </p>
-<p class="img-caption"><strong>Figure 5.</strong> Inspection Configuration</p> 
+<p class="img-caption"><strong>Figure 5.</strong> Configure inspections.</p>
 
-<p class="note"><strong>Note:</strong> If you wish to change the behavior of specific
-inspection notifications, you can change the inspection severity, for example from <em>warning</em>
+<p class="note"><strong>Note:</strong> To change the behavior of specific
+inspection notifications, change the inspection severity, for example from <em>warning</em>
 to <em>error</em>. </p>
 
 
@@ -316,7 +367,7 @@
 
 
 
-<h4>Running Inspections from the command line</h4>
+<h4>Running inspections from the command line</h4>
 <p>You can also run {@code lint} inspections from the command line in your SDK directory. </p>
 <pre>
 sdk$ lint [flags] <project directories>
@@ -327,25 +378,127 @@
 
 
 <p>For more information, see
-<a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with {@code lint}</a> and
-<a href="{@docRoot}tools/help/lint.html">lint tool</a>.</p>
+<a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with {@code lint}</a>
+and <a href="{@docRoot}tools/help/lint.html">lint tool</a>.</p>
+
+
+
+<h3 id="annotations">Annotations in Android Studio</h3>
+<p>Android Studio supports annotations for variables, parameters, and return values to help you
+catch bugs, such as null pointer exceptions and resource type conflicts. The
+<a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a> packages
+the {@link android.support.annotation Support-Annotations} library
+in the Android Support Repository for use with Android
+Studio. Android Studio validates the configured annotations during code inspection. </p>
+
+<p>To add annotations to your code in Android Studio, first add a dependency for the
+{@link android.support.annotation Support-Annotations} library:</p>
+<ol>
+ <li>Select <strong>File &gt; Project Structure</strong>.</li>
+ <li>In the <em>Project Structure</em> dialog, select the desired module, click the
+ <strong>Dependencies</strong> tab. </li>
+ <li>Click the <img src="{@docRoot}images/tools/studio-add-icon.png"/> icon to include a
+ <strong>Library dependency</strong>.</li>
+ <li>In the <em>Choose Library Dependency</em> dialog, select <code>support-annotations</code> and
+ click <strong>Ok</strong>. </li>
+</ol> 
+
+<p>The <code>build.gradle</code> file is updated with the <code>support-annotations</code>
+dependency.</p>
+
+<p>You can also manually add this dependency to your <code>build.gradle</code> file, as shown in
+the following example.  </p>
+
+<pre>
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile 'com.android.support:appcompat-v7:22.0.0'
+    <strong>compile 'com.android.support:support-annotations:22.0.0'</strong>
+}
+</pre>
+
+
+
+<h4>Inferring nullability</h4>
+<p>A nullability analysis scans the contracts throughout the method hierarchies in your code to
+detect:</p>
+<ul>
+ <li>Calling methods that can return null </li>
+ <li>Methods that should not return null </li>
+ <li>Variables, such as fields, local variables, and parameters, that can be null </li>
+ <li>Variables, such as fields, local variables, and parameters, that cannot hold a null value </li>
+</ul>
+
+<p>The analysis then automatically inserts the appropriate null annotations in the detected
+locations. </p>
+
+<p>To run a nullability analysis in Android Studio,
+select the <strong>Analyze &gt; Infer Nullity</strong>
+menu option. Android Studio inserts the Android
+{@link android.support.annotation.Nullable @Nullable} and
+{@link android.support.annotation.NonNull @NonNull} annotations in detected locations
+in your code. After running a null analysis, it's good practice to verify the injected
+annotations.</p>
+
+<p class="note"><strong>Note:</strong> The nullability analysis may insert the IntelliJ
+<a class="external-link" href="https://www.jetbrains.com/idea/help/-nullable-and-notnull-annotations.html?search=annotations">
+<code>&#64;Nullable</code></a> and
+<a class="external-link" href="https://www.jetbrains.com/idea/help/-nullable-and-notnull-annotations.html?search=annotations">
+<code>&#64;NotNull</code></a> annotations instead of the Android null annotations. When running
+a null analysis, manually search and replace any IntelliJ annotations or include
+<code>com.intellij:annotations:12.0</code> as a compile dependency in your
+<code>build.gradle</code> file. This example includes the IntelliJ annotations 12.0 library as a
+dependency in the <code>build.gradle</code> file:
+
+<pre>
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile 'com.android.support:appcompat-v7:22.0.0'
+    compile 'com.android.support:support-annotations:22.0.0'
+    <strong>compile 'com.intellij:annotations:12.0'</strong>
+}
+</pre>
+
+</p>
+
+
+<h4>Validating annotations</h4>
+<p>You can also manually add nullability, resource, and enumerated annotations throughout your code
+to perform validations for a variety of reference values, such as
+<a href="{@docRoot}reference/android/R.string.html"><code>R.string</code></a> resources,
+<a href="{@docRoot}guide/topics/resources/drawable-resource.htm"><code>Drawable</code></a>
+resources,
+<a href="{@docRoot}reference/android/graphics/Color.html"><code>Color</code></a> resources,
+and enumerated constants. </p>
+
+<p>Run <strong>Analyze &gt; Inspect Code</strong> to validate the configured annotations. </p>
+
+<p>For a complete list of the supported annotations, either use the auto-complete feature to display
+the available options for the <code>import android.support.annotation.</code> statement or
+view the contents of the
+{@link android.support.annotation Support-Annotations}
+library. </p>
+
+<p>For more details about Android annotations, see
+<a href="{@docRoot}tools/debugging/annotations.html">Improving Code Inspection with Annotations</a>.
+
 
 
 <h3>Dynamic layout preview</h3>
 <p>Android Studio allows you to work with layouts in both a <em>Design View</em> </p>
 <p><img src="{@docRoot}images/tools/studio-helloworld-design.png" alt="" />
 </p>
-    <p class="img-caption"><strong>Figure 6.</strong> Hello World App with Design View</p>
+    <p class="img-caption"><strong>Figure 6.</strong> Hello World App with Design View.</p>
 
 <p>and a <em>Text View</em>. </p>
 
     <p><img src="{@docRoot}images/tools/studio-helloworld-text.png" alt="" />
-    <pclass="img-caption"><strong>Figure 7.</strong> Hello World App with Text View</p>
+    <pclass="img-caption"><strong>Figure 7.</strong> Hello World App with text view.</p>
 
 <p>Easily select and preview layout changes for different device images, display
 densities, UI modes, locales, and Android versions (multi-API version rendering).
     <p><img src="{@docRoot}images/tools/studio-api-version-rendering.png" /></p>
-    <p class="img-caption"><strong>Figure 8.</strong> API Version Rendering</p>
+    <p class="img-caption"><strong>Figure 8.</strong> Multi-API version rendering.</p>
 
 
 <p>From the Design View, you can drag and drop elements from the Palette to the Preview or
@@ -372,17 +525,17 @@
 <h2 id="install-updates">Installation, Setup, and Update Management</h2>
 
 <h3>Android Studio installation and setup wizards</h3>
-<p>An updated installation and setup wizards walk you through a step-by-step installation
-and setup process as the wizard checks for system requirements, such as the Java Development
-Kit (JDK) and available RAM, and then prompts for optional installation options, such as the
-Intel&#174; HAXM emulator accelerator.</p>
+<p>When you begin the installation process, an installation and setup wizard walks you through
+a step-by-step installation and setup process as the wizard checks for system requirements,
+such as the Java Development Kit (JDK) and available RAM, and then prompts for optional
+installation options, such as the Intel&#174; HAXM emulator accelerator.</p>
 
-<p>An updated setup wizard walks you through the setup processes as
+<p>During the installation process, a setup wizard walks you through the setup processes as
 the wizard updates your system image and emulation requirements, such GPU, and then creates
 an optimized default Android Virtual Device (AVD) based on Android 5 (Lollipop) for speedy and
 reliable emulation. </p>
 <p><img src="{@docRoot}images/tools/studio-setup-wizard.png" /></p>
-<p class="img-caption"><strong>Figure 9.</strong> Setup Wizard</p>
+<p class="img-caption"><strong>Figure 9.</strong> Installation and setup wizard.</p>
 
 
 <h3>Expanded template and form factor support</h3>
@@ -390,11 +543,11 @@
 types. </p>
 
     <h4> Android Wear and TV support</h4>
-    <p>For easy cross-platform development, the Project Wizard provides new templates for
+    <p>For easy cross-platform development, the Project Wizard provides templates for
     creating your apps for Android Wear and TV. </p>
     <p><img src="{@docRoot}images/tools/studio-tvwearsupport.png"  />
 
-      <p class="img-caption"><strong>Figure 10.</strong> Supported Form Factors</p>
+      <p class="img-caption"><strong>Figure 10.</strong> Supported form factors.</p>
     <p>During app creation, the Project Wizard also displays an API Level dialog to help you choose
     the best <em>minSdkVersion</em> for your project.</p>
 
@@ -404,7 +557,26 @@
     and create a cloud end-point is as easy as selecting <em>File > New Module > App Engine Java
     Servlet Module</em> and specifying the module, package, and client names. </p>
     <p><img src="{@docRoot}images/tools/studio-cloudmodule.png" /></p>
-    <p class="img-caption"><strong>Figure 11.</strong> Setup Wizard</p>
+    <p class="img-caption"><strong>Figure 11.</strong> Google App Engine integration.</p>
+
+
+<h3>Easy access to project and file settings</h3>
+<p>Android Studio provides setting dialogs so you can manage the most important project and file
+settings from the <strong>File</strong> menus as well as the build and configuration files. For
+example, you can use the <strong>File &gt; Project Structure</strong> menu or
+the <code>build.gradle</code> file to update your <code>productFlavor</code> settings.
+Additional settings from the <strong>File</strong> menus include:
+<ul>
+ <li>SDK and JDK location </li>
+ <li>SDK version </li>
+ <li>Gradle and Android Plugin for Gradle versions </li>
+ <li>Build tools version </li>
+ <li>Multidex setting</li>
+ <li>Product flavors </li>
+ <li>Build types </li>
+ <li>Dependencies </li>
+</ul>
+</p>
 
 
 
@@ -451,13 +623,14 @@
 <p>Android Studio supports HTTP proxy settings so you can run Android Studio behind a firewall or
 secure network. To set the HTTP proxy settings in Android Studio:</p>
 <ol>
- <li>From the main menu choose <strong>File &gt; Settings &gt; IDE Setting -- HTTP Proxy</strong>.
+ <li>From the main menu choose <strong>File &gt; Settings &gt; Appearance & Behavior -- System
+ Settings -- HTTP Proxy</strong>.
 
 <li>In Android Studio, open the IDE Settings dialog.
   <ul>
-     <li>On Windows and Linux, choose 
+     <li>On Windows and Linux, choose
      <strong>File &gt; Settings &gt; IDE Setting -- HTTP Proxy</strong>. </li>
-     <li>On Mac, choose 
+     <li>On Mac, choose
      <strong>Android Studio &gt; Preferences &gt; IDE Setting -- HTTP Proxy</strong>. </li>
    </ul>
  The HTTP Proxy page appears.</li>
@@ -544,36 +717,39 @@
 
 <h2 id="other">Other Highlights</h2>
 
-<h3> Translation Editor</h3>
-<p>Multi-language support is enhanced with the Translation Editor plugin so you can easily add
-locales to the app's translation file. Color codes indicate whether a locale is complete or
-still missing string translations. Also, you can use the plugin to export your strings to the
-Google Play Developer Console for translation, then download and import your translations back
-into your project. </p>
+<h3 id="trans-editor"> Translations Editor</h3>
+<p>Multi-language support is enhanced with the Translations Editor plugin so you can easily add
+a variety of locales to the app's translation file. With
+<a href="https://tools.ietf.org/html/bcp47">BCP 47</a> support, the editor combines language and
+region codes into a single selection for targeted localizations. Color codes indicate whether a
+locale is complete or still missing string translations. You can also use the plugin to export
+your strings to the
+<a href="{@docRoot}distribute/googleplay/developer-console.html">Google Play Developer Console</a>
+for translation, then download and import your translations back into your project. </p>
 
-<p>To access the Translation Editor, open a <code>strings.xml</code> file and click the
+<p>To access the Translations Editor, open a <code>strings.xml</code> file and click the
 <strong>Open Editor</strong> link.  </p>
 
     <img src="{@docRoot}images/tools/studio-translationeditoropen.png" />
-    <p class="img-caption"><strong>Figure 12.</strong> Translation Editor</p>
+    <p class="img-caption"><strong>Figure 12.</strong> Add locales and strings in the
+    Translations Editor.</p>
 
 
 <h3> Editor support for the latest Android APIs</h3>
 <p>Android Studio supports the
 <a href="{@docRoot}design/material/index.html">Material Design</a></li> themes, widgets, and
 graphics, such as shadow layers and API version rendering (showing the layout across different
-UI versions). Also, the drawable XML tags and attributes, such as &lt;ripple&gt;
-and &lt;animated-selector&gt;, are supported.</p>
+UI versions). Also, the drawable XML tags and attributes, such as <code>&lt;ripple&gt;</code>
+and <code>&lt;animated-selector&gt;</code>, are supported.</p>
 
 
 <h3 id="git-samples"> Easy access to Android code samples on GitHub</h3>
-<p>Clicking <strong>Import Samples</strong> from the <strong>File</strong> menu or <em>Welcome</em> page
-
-provides seamless access to Google code samples on GitHub.</p>
+<p>Clicking <strong>Import Samples</strong> from the <strong>File</strong> menu or <em>Welcome</em>
+page provides seamless access to Google code samples on GitHub.</p>
     <p><img src="{@docRoot}images/tools/studio-samples-githubaccess.png" /></p>
-    <p class="img-caption"><strong>Figure 13.</strong> Code Sample Access</p>
+    <p class="img-caption"><strong>Figure 13.</strong> Get code samples from GitHub.</p>
 
     <p><img src="{@docRoot}images/tools/studio-sample-in-editor.png" /></p>
-    <p class="img-caption"><strong>Figure 14.</strong> Imported Code Sample</p>
+    <p class="img-caption"><strong>Figure 14.</strong> Imported code sample.</p>
 
 
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 3f4b111..88a2674 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -128,6 +128,7 @@
       <li><a href="<?cs var:toroot ?>tools/debugging/improving-w-lint.html"><span class="en">Improving Your Code with lint</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/debugging/debugging-ui.html"><span class="en">Optimizing your UI</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/debugging/debugging-tracing.html"><span class="en">Profiling with Traceview and dmtracedump</span></a></li>
+      <li><a href="<?cs var:toroot ?>tools/debugging/annotations.html"><span class="en">Improving Code Inspection with Annotations</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/debugging/systrace.html"><span class="en">Analyzing Display and Performance</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/debugging/debugging-memory.html">Investigating Your RAM Usage</a></li>
       <li><a href="<?cs var:toroot ?>tools/debugging/debugging-devtools.html"><span class="en">Using the Dev Tools App</span></a></li>
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index b32dcc6..feb8052 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -380,7 +380,7 @@
 
             final long transformPtr = (transform != null) ? transform.native_instance : 0;
 
-            nativeRenderPage(mNativeDocument, mNativePage, destination.getSkBitmap(), contentLeft,
+            nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft,
                     contentTop, contentRight, contentBottom, transformPtr, renderMode);
         }
 
@@ -425,7 +425,7 @@
     private static native void nativeClose(long documentPtr);
     private static native int nativeGetPageCount(long documentPtr);
     private static native boolean nativeScaleForPrinting(long documentPtr);
-    private static native void nativeRenderPage(long documentPtr, long pagePtr, long destPtr,
+    private static native void nativeRenderPage(long documentPtr, long pagePtr, Bitmap dest,
             int destLeft, int destTop, int destRight, int destBottom, long matrixPtr, int renderMode);
     private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex,
             Point outSize);
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index ed91d70..72cb062 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -486,16 +486,6 @@
             }
         }
         args.addInts(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
-        if (keymasterDigests.length > 0) {
-            // TODO: Remove MAC length constraint once Keymaster API no longer requires it.
-            // This code will blow up if mode than one digest is specified.
-            int digestOutputSizeBytes =
-                    KeymasterUtils.getDigestOutputSizeBytes(keymasterDigests[0]);
-            if (digestOutputSizeBytes != -1) {
-                // TODO: Switch to bits instead of bytes, once this is fixed in Keymaster
-                args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, digestOutputSizeBytes);
-            }
-        }
         if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
             if (keymasterDigests.length == 0) {
                 throw new KeyStoreException("At least one digest algorithm must be specified"
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 1563863..82d328b 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -16,10 +16,12 @@
 
 package android.security;
 
+import android.app.ActivityThread;
+import android.app.Application;
 import com.android.org.conscrypt.NativeConstants;
 
 import android.content.Context;
-import android.hardware.fingerprint.IFingerprintService;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -77,11 +79,27 @@
     private int mError = NO_ERROR;
 
     private final IKeystoreService mBinder;
+    private final Context mContext;
 
     private IBinder mToken;
 
     private KeyStore(IKeystoreService binder) {
         mBinder = binder;
+        mContext = getContext();
+    }
+
+    private static Context getContext() {
+        ActivityThread activityThread = ActivityThread.currentActivityThread();
+        if (activityThread == null) {
+            throw new IllegalStateException(
+                    "Failed to obtain application Context: no ActivityThread");
+        }
+        Application application = activityThread.getApplication();
+        if (application == null) {
+            throw new IllegalStateException(
+                    "Failed to obtain application Context: no Application");
+        }
+        return application;
     }
 
     public static KeyStore getInstance() {
@@ -618,23 +636,18 @@
         }
     }
 
-    private static long getFingerprintOnlySid() {
-        IFingerprintService service = IFingerprintService.Stub.asInterface(
-                ServiceManager.getService(Context.FINGERPRINT_SERVICE));
-        if (service == null) {
+    private long getFingerprintOnlySid() {
+        FingerprintManager fingerprintManager =
+                mContext.getSystemService(FingerprintManager.class);
+        if (fingerprintManager == null) {
             return 0;
         }
 
-        try {
-            long deviceId = 0; // TODO: plumb hardware id to FPMS
-            if (!service.isHardwareDetected(deviceId)) {
-                return 0;
-            }
-
-            return service.getAuthenticatorId();
-        } catch (RemoteException e) {
-            throw new IllegalStateException("Failed to communicate with fingerprint service", e);
+        if (!fingerprintManager.isHardwareDetected()) {
+            return 0;
         }
+
+        return fingerprintManager.getAuthenticatorId();
     }
 
     /**
diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java
index 917f716..20dd524 100644
--- a/keystore/java/android/security/KeyStoreCipherSpi.java
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -22,6 +22,7 @@
 import android.security.keymaster.OperationResult;
 
 import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.Key;
@@ -298,38 +299,36 @@
         mAdditionalEntropyForBegin = null;
         if (opResult == null) {
             throw new KeyStoreConnectException();
-        } else if ((opResult.resultCode != KeyStore.NO_ERROR)
-                && (opResult.resultCode != KeyStore.OP_AUTH_NEEDED)) {
-            switch (opResult.resultCode) {
-                case KeymasterDefs.KM_ERROR_INVALID_NONCE:
-                    throw new InvalidAlgorithmParameterException("Invalid IV");
-            }
-            throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
         }
 
-        if (opResult.token == null) {
-            throw new IllegalStateException("Keystore returned null operation token");
-        }
-        // The operation handle/token is now either valid for use immediately or needs to be
-        // authorized through user authentication (if the error code was OP_AUTH_NEEDED).
+        // Store operation token and handle regardless of the error code returned by KeyStore to
+        // ensure that the operation gets aborted immediately if the code below throws an exception.
         mOperationToken = opResult.token;
         mOperationHandle = opResult.operationHandle;
+
+        // If necessary, throw an exception due to KeyStore operation having failed.
+        GeneralSecurityException e = KeyStoreCryptoOperationUtils.getExceptionForCipherInit(
+                mKeyStore, mKey, opResult.resultCode);
+        if (e != null) {
+            if (e instanceof InvalidKeyException) {
+                throw (InvalidKeyException) e;
+            } else if (e instanceof InvalidAlgorithmParameterException) {
+                throw (InvalidAlgorithmParameterException) e;
+            } else {
+                throw new RuntimeException("Unexpected exception type", e);
+            }
+        }
+
+        if (mOperationToken == null) {
+            throw new IllegalStateException("Keystore returned null operation token");
+        }
+
         loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
         mFirstOperationInitiated = true;
         mIvHasBeenUsed = true;
         mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
                 new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
                         mKeyStore, opResult.token));
-
-        if (opResult.resultCode != KeyStore.NO_ERROR) {
-            // The operation requires user authentication. Check whether such authentication is
-            // possible (e.g., the key may have been permanently invalidated).
-            InvalidKeyException e =
-                    mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
-            if (!(e instanceof UserNotAuthenticatedException)) {
-                throw e;
-            }
-        }
     }
 
     @Override
diff --git a/keystore/java/android/security/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
new file mode 100644
index 0000000..e5933ad
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreCryptoOperationUtils.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 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.security;
+
+import android.security.keymaster.KeymasterDefs;
+
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+
+/**
+ * Assorted utility methods for implementing crypto operations on top of KeyStore.
+ *
+ * @hide
+ */
+abstract class KeyStoreCryptoOperationUtils {
+    private KeyStoreCryptoOperationUtils() {}
+
+    /**
+     * Returns the {@link InvalidKeyException} to be thrown by the {@code init} method of
+     * the crypto operation in response to {@code KeyStore.begin} operation or {@code null} if
+     * the {@code init} method should succeed.
+     */
+    static InvalidKeyException getInvalidKeyExceptionForInit(
+            KeyStore keyStore, KeyStoreKey key, int beginOpResultCode) {
+        if (beginOpResultCode == KeyStore.NO_ERROR) {
+            return null;
+        }
+
+        // An error occured. However, some errors should not lead to init throwing an exception.
+        // See below.
+        InvalidKeyException e =
+                keyStore.getInvalidKeyException(key.getAlias(), beginOpResultCode);
+        switch (beginOpResultCode) {
+            case KeyStore.OP_AUTH_NEEDED:
+                // Operation needs to be authorized by authenticating the user. Don't throw an
+                // exception is such authentication is possible for this key
+                // (UserNotAuthenticatedException). An example of when it's not possible is where
+                // the key is permanently invalidated (KeyPermanentlyInvalidatedException).
+                if (e instanceof UserNotAuthenticatedException) {
+                    return null;
+                }
+                break;
+        }
+        return e;
+    }
+
+    /**
+     * Returns the exception to be thrown by the {@code Cipher.init} method of the crypto operation
+     * in response to {@code KeyStore.begin} operation or {@code null} if the {@code init} method
+     * should succeed.
+     */
+    static GeneralSecurityException getExceptionForCipherInit(
+            KeyStore keyStore, KeyStoreKey key, int beginOpResultCode) {
+        if (beginOpResultCode == KeyStore.NO_ERROR) {
+            return null;
+        }
+
+        // Cipher-specific cases
+        switch (beginOpResultCode) {
+            case KeymasterDefs.KM_ERROR_INVALID_NONCE:
+                return new InvalidAlgorithmParameterException("Invalid IV");
+            case KeymasterDefs.KM_ERROR_CALLER_NONCE_PROHIBITED:
+                return new InvalidAlgorithmParameterException("Caller-provided IV not permitted");
+        }
+
+        // General cases
+        return getInvalidKeyExceptionForInit(keyStore, key, beginOpResultCode);
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java
index 4590b9c..e993b50 100644
--- a/keystore/java/android/security/KeyStoreHmacSpi.java
+++ b/keystore/java/android/security/KeyStoreHmacSpi.java
@@ -67,7 +67,7 @@
 
     private final KeyStore mKeyStore = KeyStore.getInstance();
     private final int mKeymasterDigest;
-    private final int mMacSizeBytes;
+    private final int mMacSizeBits;
 
     // Fields below are populated by engineInit and should be preserved after engineDoFinal.
     private KeyStoreSecretKey mKey;
@@ -79,12 +79,12 @@
 
     protected KeyStoreHmacSpi(int keymasterDigest) {
         mKeymasterDigest = keymasterDigest;
-        mMacSizeBytes = KeymasterUtils.getDigestOutputSizeBytes(keymasterDigest);
+        mMacSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
     }
 
     @Override
     protected int engineGetMacLength() {
-        return mMacSizeBytes;
+        return (mMacSizeBits + 7) / 8;
     }
 
     @Override
@@ -158,41 +158,39 @@
         KeymasterArguments keymasterArgs = new KeymasterArguments();
         keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC);
         keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
+        keymasterArgs.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mMacSizeBits);
 
+        KeymasterArguments keymasterOutputArgs = new KeymasterArguments();
         OperationResult opResult = mKeyStore.begin(
                 mKey.getAlias(),
                 KeymasterDefs.KM_PURPOSE_SIGN,
                 true,
                 keymasterArgs,
-                null,
-                new KeymasterArguments());
+                null, // no additional entropy needed for HMAC because it's deterministic
+                keymasterOutputArgs);
         if (opResult == null) {
             throw new KeyStoreConnectException();
-        } else if ((opResult.resultCode != KeyStore.NO_ERROR)
-                && (opResult.resultCode != KeyStore.OP_AUTH_NEEDED)) {
-            throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
         }
 
-        if (opResult.token == null) {
-            throw new IllegalStateException("Keystore returned null operation token");
-        }
-        // The operation handle/token is now either valid for use immediately or needs to be
-        // authorized through user authentication (if the error code was OP_AUTH_NEEDED).
+        // Store operation token and handle regardless of the error code returned by KeyStore to
+        // ensure that the operation gets aborted immediately if the code below throws an exception.
         mOperationToken = opResult.token;
         mOperationHandle = opResult.operationHandle;
+
+        // If necessary, throw an exception due to KeyStore operation having failed.
+        InvalidKeyException e = KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(
+                mKeyStore, mKey, opResult.resultCode);
+        if (e != null) {
+            throw e;
+        }
+
+        if (mOperationToken == null) {
+            throw new IllegalStateException("Keystore returned null operation token");
+        }
+
         mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
                 new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
                         mKeyStore, mOperationToken));
-
-        if (opResult.resultCode != KeyStore.NO_ERROR) {
-            // The operation requires user authentication. Check whether such authentication is
-            // possible (e.g., the key may have been permanently invalidated).
-            InvalidKeyException e =
-                    mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
-            if (!(e instanceof UserNotAuthenticatedException)) {
-                throw e;
-            }
-        }
     }
 
     @Override
diff --git a/keystore/java/android/security/KeyStoreKey.java b/keystore/java/android/security/KeyStoreKey.java
new file mode 100644
index 0000000..7a34829
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreKey.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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.security;
+
+import java.security.Key;
+
+/**
+ * {@link Key} backed by AndroidKeyStore.
+ *
+ * @hide
+ */
+public class KeyStoreKey implements Key {
+    private final String mAlias;
+    private final String mAlgorithm;
+
+    public KeyStoreKey(String alias, String algorithm) {
+        mAlias = alias;
+        mAlgorithm = algorithm;
+    }
+
+    String getAlias() {
+        return mAlias;
+    }
+
+    @Override
+    public String getAlgorithm() {
+        return mAlgorithm;
+    }
+
+    @Override
+    public String getFormat() {
+        // This key does not export its key material
+        return null;
+    }
+
+    @Override
+    public byte[] getEncoded() {
+        // This key does not export its key material
+        return null;
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
index 20f6042..68b5751 100644
--- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
@@ -45,7 +45,7 @@
         protected HmacBase(int keymasterDigest) {
             super(KeymasterDefs.KM_ALGORITHM_HMAC,
                     keymasterDigest,
-                    KeymasterUtils.getDigestOutputSizeBytes(keymasterDigest) * 8);
+                    KeymasterUtils.getDigestOutputSizeBits(keymasterDigest));
         }
     }
 
@@ -120,13 +120,6 @@
         args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
         if (mKeymasterDigest != -1) {
             args.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
-            int digestOutputSizeBytes =
-                    KeymasterUtils.getDigestOutputSizeBytes(mKeymasterDigest);
-            if (digestOutputSizeBytes != -1) {
-                // TODO: Remove MAC length constraint once Keymaster API no longer requires it.
-                // TODO: Switch to bits instead of bytes, once this is fixed in Keymaster
-                args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, digestOutputSizeBytes);
-            }
         }
         if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
             if (mKeymasterDigest == -1) {
diff --git a/keystore/java/android/security/KeyStoreSecretKey.java b/keystore/java/android/security/KeyStoreSecretKey.java
index 7f0e3d3..ee25465 100644
--- a/keystore/java/android/security/KeyStoreSecretKey.java
+++ b/keystore/java/android/security/KeyStoreSecretKey.java
@@ -23,33 +23,9 @@
  *
  * @hide
  */
-public class KeyStoreSecretKey implements SecretKey {
-    private final String mAlias;
-    private final String mAlgorithm;
+public class KeyStoreSecretKey extends KeyStoreKey implements SecretKey {
 
     public KeyStoreSecretKey(String alias, String algorithm) {
-        mAlias = alias;
-        mAlgorithm = algorithm;
-    }
-
-    String getAlias() {
-        return mAlias;
-    }
-
-    @Override
-    public String getAlgorithm() {
-        return mAlgorithm;
-    }
-
-    @Override
-    public String getFormat() {
-        // This key does not export its key material
-        return null;
-    }
-
-    @Override
-    public byte[] getEncoded() {
-        // This key does not export its key material
-        return null;
+        super(alias, algorithm);
     }
 }
diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java
index 3ccb588..aa44ecd 100644
--- a/keystore/java/android/security/KeymasterUtils.java
+++ b/keystore/java/android/security/KeymasterUtils.java
@@ -179,22 +179,22 @@
         return result;
     }
 
-    public static int getDigestOutputSizeBytes(int keymasterDigest) {
+    public static int getDigestOutputSizeBits(int keymasterDigest) {
         switch (keymasterDigest) {
             case KeymasterDefs.KM_DIGEST_NONE:
                 return -1;
             case KeymasterDefs.KM_DIGEST_MD5:
-                return 128 / 8;
+                return 128;
             case KeymasterDefs.KM_DIGEST_SHA1:
-                return 160 / 8;
+                return 160;
             case KeymasterDefs.KM_DIGEST_SHA_2_224:
-                return 224 / 8;
+                return 224;
             case KeymasterDefs.KM_DIGEST_SHA_2_256:
-                return 256 / 8;
+                return 256;
             case KeymasterDefs.KM_DIGEST_SHA_2_384:
-                return 384 / 8;
+                return 384;
             case KeymasterDefs.KM_DIGEST_SHA_2_512:
-                return 512 / 8;
+                return 512;
             default:
                 throw new IllegalArgumentException("Unknown digest: " + keymasterDigest);
         }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index a33fa59..77adb39 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1953,21 +1953,16 @@
 
         TrackInfo(Parcel in) {
             mTrackType = in.readInt();
-            // TODO: parcel in the full MediaFormat
+            // TODO: parcel in the full MediaFormat; currently we are using createSubtitleFormat
+            // even for audio/video tracks, meaning we only set the mime and language.
+            String mime = in.readString();
             String language = in.readString();
+            mFormat = MediaFormat.createSubtitleFormat(mime, language);
 
-            if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
-                mFormat = MediaFormat.createSubtitleFormat(
-                    MEDIA_MIMETYPE_TEXT_SUBRIP, language);
-            } else if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-                String mime = in.readString();
-                mFormat = MediaFormat.createSubtitleFormat(mime, language);
+            if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
                 mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.readInt());
                 mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.readInt());
                 mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.readInt());
-            } else {
-                mFormat = new MediaFormat();
-                mFormat.setString(MediaFormat.KEY_LANGUAGE, language);
             }
         }
 
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java
index dc6760d..ecc87e7 100644
--- a/media/java/android/media/MediaSync.java
+++ b/media/java/android/media/MediaSync.java
@@ -199,6 +199,7 @@
     private final Object mAudioLock = new Object();
     private AudioTrack mAudioTrack = null;
     private List<AudioBuffer> mAudioBuffers = new LinkedList<AudioBuffer>();
+    // this is only used for paused/running decisions, so it is not affected by clock drift
     private float mPlaybackRate = 0.0f;
 
     private long mNativeContext;
@@ -459,36 +460,11 @@
      * @throws IllegalArgumentException if the settings are not supported.
      */
     public void setPlaybackSettings(@NonNull PlaybackSettings settings) {
-        float rate;
-        try {
-            rate = settings.getSpeed();
-
-            // rate is specified
-            if (mAudioTrack != null) {
-                try {
-                    if (rate == 0.0) {
-                        mAudioTrack.pause();
-                    } else {
-                        mAudioTrack.setPlaybackSettings(settings);
-                        mAudioTrack.play();
-                    }
-                } catch (IllegalStateException e) {
-                    throw e;
-                }
-            }
-
-            synchronized(mAudioLock) {
-                mPlaybackRate = rate;
-            }
-            if (mPlaybackRate != 0.0 && mAudioThread != null) {
-                postRenderAudio(0);
-            }
-            native_setPlaybackRate(mPlaybackRate);
-        } catch (IllegalStateException e) {
-            // rate is not specified; still, propagate settings to audio track
-            if (mAudioTrack != null) {
-                mAudioTrack.setPlaybackSettings(settings);
-            }
+        synchronized(mAudioLock) {
+            mPlaybackRate = native_setPlaybackSettings(settings);;
+        }
+        if (mPlaybackRate != 0.0 && mAudioThread != null) {
+            postRenderAudio(0);
         }
     }
 
@@ -501,18 +477,9 @@
      *     been initialized.
      */
     @NonNull
-    public PlaybackSettings getPlaybackSettings() {
-        if (mAudioTrack != null) {
-            return mAudioTrack.getPlaybackSettings();
-        } else {
-            PlaybackSettings settings = new PlaybackSettings();
-            settings.allowDefaults();
-            settings.setSpeed(mPlaybackRate);
-            return settings;
-        }
-    }
+    public native PlaybackSettings getPlaybackSettings();
 
-    private native final void native_setPlaybackRate(float rate);
+    private native float native_setPlaybackSettings(@NonNull PlaybackSettings settings);
 
     /**
      * Sets A/V sync mode.
@@ -523,7 +490,16 @@
      * initialized.
      * @throws IllegalArgumentException if settings are not supported.
      */
-    public native void setSyncSettings(@NonNull SyncSettings settings);
+    public void setSyncSettings(@NonNull SyncSettings settings) {
+        synchronized(mAudioLock) {
+            mPlaybackRate = native_setSyncSettings(settings);;
+        }
+        if (mPlaybackRate != 0.0 && mAudioThread != null) {
+            postRenderAudio(0);
+        }
+    }
+
+    private native float native_setSyncSettings(@NonNull SyncSettings settings);
 
     /**
      * Gets the A/V sync mode.
diff --git a/media/java/android/media/midi/MidiReceiver.java b/media/java/android/media/midi/MidiReceiver.java
index d069075..f8799d4 100644
--- a/media/java/android/media/midi/MidiReceiver.java
+++ b/media/java/android/media/midi/MidiReceiver.java
@@ -23,6 +23,10 @@
  */
 abstract public class MidiReceiver {
     /**
+     * Although public, this method should be considered a private implementation
+     * detail. Client code should call {@link #send} or {@link #sendWithTimestamp}
+     * instead.
+     *
      * Called to pass MIDI data to the receiver.
      * May fail if count exceeds {@link #getMaxMessageSize}.
      *
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 88a6771..59fb6d6 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -299,15 +299,16 @@
         return NULL;
     }
 
-    SkBitmap *bitmap = GraphicsJNI::getSkBitmap(env, jBitmap);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(env, jBitmap, &bitmap);
 
-    bitmap->lockPixels();
-    rotate((uint16_t*)bitmap->getPixels(),
+    bitmap.lockPixels();
+    rotate((uint16_t*)bitmap.getPixels(),
            (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)),
            videoFrame->mWidth,
            videoFrame->mHeight,
            videoFrame->mRotationAngle);
-    bitmap->unlockPixels();
+    bitmap.unlockPixels();
 
     if (videoFrame->mDisplayWidth  != videoFrame->mWidth ||
         videoFrame->mDisplayHeight != videoFrame->mHeight) {
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 2c61779..5b55a61 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -174,6 +174,8 @@
     } else {  // Throw exception!
         if ( opStatus == (status_t) INVALID_OPERATION ) {
             jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        } else if ( opStatus == (status_t) BAD_VALUE ) {
+            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
             jniThrowException(env, "java/lang/SecurityException", NULL);
         } else if ( opStatus != (status_t) OK ) {
@@ -442,8 +444,33 @@
             pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode,
             pbs.audioStretchModeSet, pbs.audioRate.mStretchMode);
 
-    // TODO: pass playback settings to mediaplayer when audiotrack supports it
-    process_media_player_call(env, thiz, mp->setPlaybackRate(pbs.audioRate.mSpeed), NULL, NULL);
+    AudioPlaybackRate rate;
+    status_t err = mp->getPlaybackSettings(&rate);
+    if (err == OK) {
+        bool updatedRate = false;
+        if (pbs.speedSet) {
+            rate.mSpeed = pbs.audioRate.mSpeed;
+            updatedRate = true;
+        }
+        if (pbs.pitchSet) {
+            rate.mPitch = pbs.audioRate.mPitch;
+            updatedRate = true;
+        }
+        if (pbs.audioFallbackModeSet) {
+            rate.mFallbackMode = pbs.audioRate.mFallbackMode;
+            updatedRate = true;
+        }
+        if (pbs.audioStretchModeSet) {
+            rate.mStretchMode = pbs.audioRate.mStretchMode;
+            updatedRate = true;
+        }
+        if (updatedRate) {
+            err = mp->setPlaybackSettings(rate);
+        }
+    }
+    process_media_player_call(
+            env, thiz, err,
+            "java/lang/IllegalStateException", "unexpected error");
 }
 
 static jobject
@@ -457,15 +484,9 @@
 
     PlaybackSettings pbs;
     AudioPlaybackRate &audioRate = pbs.audioRate;
-
-    audioRate.mSpeed = 1.0f;
-    audioRate.mPitch = 1.0f;
-    audioRate.mFallbackMode = AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
-    audioRate.mStretchMode = AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
-
-    // TODO: get this from mediaplayer when audiotrack supports it
-    // process_media_player_call(
-    //        env, thiz, mp->getPlaybackSettings(&audioRate), NULL, NULL);
+    process_media_player_call(
+            env, thiz, mp->getPlaybackSettings(&audioRate),
+            "java/lang/IllegalStateException", "unexpected error");
     ALOGV("getPlaybackSettings: %f %f %d %d",
             audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
 
@@ -489,13 +510,35 @@
     SyncSettings scs;
     scs.fillFromJobject(env, gSyncSettingsFields, settings);
     ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f",
-            scs.syncSourceSet, scs.syncSource,
-            scs.audioAdjustModeSet, scs.audioAdjustMode,
-            scs.toleranceSet, scs.tolerance,
-            scs.frameRateSet, scs.frameRate);
+          scs.syncSourceSet, scs.sync.mSource,
+          scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode,
+          scs.toleranceSet, scs.sync.mTolerance,
+          scs.frameRateSet, scs.frameRate);
 
-    // TODO: pass sync settings to mediaplayer when it supports it
-    // process_media_player_call(env, thiz, mp->setSyncSettings(scs), NULL, NULL);
+    AVSyncSettings avsync;
+    float videoFrameRate;
+    status_t err = mp->getSyncSettings(&avsync, &videoFrameRate);
+    if (err == OK) {
+        bool updatedSync = scs.frameRateSet;
+        if (scs.syncSourceSet) {
+            avsync.mSource = scs.sync.mSource;
+            updatedSync = true;
+        }
+        if (scs.audioAdjustModeSet) {
+            avsync.mAudioAdjustMode = scs.sync.mAudioAdjustMode;
+            updatedSync = true;
+        }
+        if (scs.toleranceSet) {
+            avsync.mTolerance = scs.sync.mTolerance;
+            updatedSync = true;
+        }
+        if (updatedSync) {
+            err = mp->setSyncSettings(avsync, scs.frameRateSet ? scs.frameRate : -1.f);
+        }
+    }
+    process_media_player_call(
+            env, thiz, err,
+            "java/lang/IllegalStateException", "unexpected error");
 }
 
 static jobject
@@ -508,21 +551,27 @@
     }
 
     SyncSettings scs;
-    scs.syncSource = 0; // SYNC_SOURCE_DEFAULT
-    scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT
-    scs.tolerance = 0.f;
-    scs.frameRate = 0.f;
+    scs.frameRate = -1.f;
+    process_media_player_call(
+            env, thiz, mp->getSyncSettings(&scs.sync, &scs.frameRate),
+            "java/lang/IllegalStateException", "unexpected error");
 
-    // TODO: get this from mediaplayer when it supports it
-    // process_media_player_call(
-    //        env, thiz, mp->getSyncSettings(&scs), NULL, NULL);
     ALOGV("getSyncSettings: %d %d %f %f",
-            scs.syncSource, scs.audioAdjustMode, scs.tolerance, scs.frameRate);
+            scs.sync.mSource, scs.sync.mAudioAdjustMode, scs.sync.mTolerance, scs.frameRate);
+
+    // sanity check settings
+    if (scs.sync.mSource >= AVSYNC_SOURCE_MAX
+            || scs.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
+            || scs.sync.mTolerance < 0.f
+            || scs.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
+        jniThrowException(env,  "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
 
     scs.syncSourceSet = true;
     scs.audioAdjustModeSet = true;
     scs.toleranceSet = true;
-    scs.frameRateSet = false;
+    scs.frameRateSet = scs.frameRate >= 0.f;
 
     return scs.asJobject(env, gSyncSettingsFields);
 }
diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp
index f192262..8ad4b71 100644
--- a/media/jni/android_media_MediaSync.cpp
+++ b/media/jni/android_media_MediaSync.cpp
@@ -21,6 +21,7 @@
 #include "android_media_MediaSync.h"
 
 #include "android_media_AudioTrack.h"
+#include "android_media_PlaybackSettings.h"
 #include "android_media_SyncSettings.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
@@ -29,6 +30,7 @@
 
 #include <gui/Surface.h>
 
+#include <media/AudioResamplerPublic.h>
 #include <media/AudioTrack.h>
 #include <media/stagefright/MediaClock.h>
 #include <media/stagefright/MediaSync.h>
@@ -47,6 +49,7 @@
 };
 
 static fields_t gFields;
+static PlaybackSettings::fields_t gPlaybackSettingsFields;
 static SyncSettings::fields_t gSyncSettingsFields;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -62,10 +65,8 @@
     return mSync->configureSurface(bufferProducer);
 }
 
-status_t JMediaSync::configureAudioTrack(
-        const sp<AudioTrack> &audioTrack,
-        int32_t nativeSampleRateInHz) {
-    return mSync->configureAudioTrack(audioTrack, nativeSampleRateInHz);
+status_t JMediaSync::configureAudioTrack(const sp<AudioTrack> &audioTrack) {
+    return mSync->configureAudioTrack(audioTrack);
 }
 
 status_t JMediaSync::createInputSurface(
@@ -73,14 +74,34 @@
     return mSync->createInputSurface(bufferProducer);
 }
 
-status_t JMediaSync::setPlaybackRate(float rate) {
-    return mSync->setPlaybackRate(rate);
-}
-
 sp<const MediaClock> JMediaSync::getMediaClock() {
     return mSync->getMediaClock();
 }
 
+status_t JMediaSync::setPlaybackSettings(const AudioPlaybackRate& rate) {
+    return mSync->setPlaybackSettings(rate);
+}
+
+void JMediaSync::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
+    mSync->getPlaybackSettings(rate);
+}
+
+status_t JMediaSync::setSyncSettings(const AVSyncSettings& syncSettings) {
+    return mSync->setSyncSettings(syncSettings);
+}
+
+void JMediaSync::getSyncSettings(AVSyncSettings* syncSettings /* nonnull */) {
+    mSync->getSyncSettings(syncSettings);
+}
+
+status_t JMediaSync::setVideoFrameRateHint(float rate) {
+    return mSync->setVideoFrameRateHint(rate);
+}
+
+float JMediaSync::getVideoFrameRate() {
+    return mSync->getVideoFrameRate();
+}
+
 status_t JMediaSync::updateQueuedAudioData(
         int sizeInBytes, int64_t presentationTimeUs) {
     return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs);
@@ -176,7 +197,7 @@
 }
 
 static void android_media_MediaSync_native_configureAudioTrack(
-        JNIEnv *env, jobject thiz, jobject jaudioTrack, jint nativeSampleRateInHz) {
+        JNIEnv *env, jobject thiz, jobject jaudioTrack) {
     ALOGV("android_media_MediaSync_configureAudioTrack");
 
     sp<JMediaSync> sync = getMediaSync(env, thiz);
@@ -194,7 +215,7 @@
         }
     }
 
-    status_t err = sync->configureAudioTrack(audioTrack, nativeSampleRateInHz);
+    status_t err = sync->configureAudioTrack(audioTrack);
 
     if (err == INVALID_OPERATION) {
         throwExceptionAsNecessary(
@@ -287,29 +308,132 @@
     return (jlong)playTimeUs;
 }
 
-static void
-android_media_MediaSync_setSyncSettings(JNIEnv *env, jobject thiz, jobject settings)
-{
+static jfloat android_media_MediaSync_setPlaybackSettings(
+        JNIEnv *env, jobject thiz, jobject settings) {
     sp<JMediaSync> sync = getMediaSync(env, thiz);
     if (sync == NULL) {
         throwExceptionAsNecessary(env, INVALID_OPERATION);
-        return;
+        return (jfloat)0.f;
+    }
+
+    PlaybackSettings pbs;
+    pbs.fillFromJobject(env, gPlaybackSettingsFields, settings);
+    ALOGV("setPlaybackSettings: %d:%f %d:%f %d:%u %d:%u",
+            pbs.speedSet, pbs.audioRate.mSpeed,
+            pbs.pitchSet, pbs.audioRate.mPitch,
+            pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode,
+            pbs.audioStretchModeSet, pbs.audioRate.mStretchMode);
+
+    AudioPlaybackRate rate;
+    sync->getPlaybackSettings(&rate);
+    bool updatedRate = false;
+    if (pbs.speedSet) {
+        rate.mSpeed = pbs.audioRate.mSpeed;
+        updatedRate = true;
+    }
+    if (pbs.pitchSet) {
+        rate.mPitch = pbs.audioRate.mPitch;
+        updatedRate = true;
+    }
+    if (pbs.audioFallbackModeSet) {
+        rate.mFallbackMode = pbs.audioRate.mFallbackMode;
+        updatedRate = true;
+    }
+    if (pbs.audioStretchModeSet) {
+        rate.mStretchMode = pbs.audioRate.mStretchMode;
+        updatedRate = true;
+    }
+    if (updatedRate) {
+        status_t err = sync->setPlaybackSettings(rate);
+        if (err != OK) {
+            throwExceptionAsNecessary(env, err);
+            return (jfloat)0.f;
+        }
+    }
+
+    sp<const MediaClock> mediaClock = sync->getMediaClock();
+    if (mediaClock == NULL) {
+        return (jfloat)0.f;
+    }
+
+    return (jfloat)mediaClock->getPlaybackRate();
+}
+
+static jobject android_media_MediaSync_getPlaybackSettings(
+        JNIEnv *env, jobject thiz) {
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
+
+    PlaybackSettings pbs;
+    AudioPlaybackRate &audioRate = pbs.audioRate;
+    sync->getPlaybackSettings(&audioRate);
+    ALOGV("getPlaybackSettings: %f %f %d %d",
+            audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
+
+    pbs.speedSet = true;
+    pbs.pitchSet = true;
+    pbs.audioFallbackModeSet = true;
+    pbs.audioStretchModeSet = true;
+
+    return pbs.asJobject(env, gPlaybackSettingsFields);
+}
+
+static jfloat android_media_MediaSync_setSyncSettings(
+        JNIEnv *env, jobject thiz, jobject settings) {
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return (jfloat)0.f;
     }
 
     SyncSettings scs;
     scs.fillFromJobject(env, gSyncSettingsFields, settings);
     ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f",
-            scs.syncSourceSet, scs.syncSource,
-            scs.audioAdjustModeSet, scs.audioAdjustMode,
-            scs.toleranceSet, scs.tolerance,
+            scs.syncSourceSet, scs.sync.mSource,
+            scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode,
+            scs.toleranceSet, scs.sync.mTolerance,
             scs.frameRateSet, scs.frameRate);
 
-    // TODO: pass sync settings to mediasync when it supports it
+    AVSyncSettings avsync;
+    sync->getSyncSettings(&avsync);
+    bool updatedSync = false;
+    status_t err = OK;
+    if (scs.syncSourceSet) {
+        avsync.mSource = scs.sync.mSource;
+        updatedSync = true;
+    }
+    if (scs.audioAdjustModeSet) {
+        avsync.mAudioAdjustMode = scs.sync.mAudioAdjustMode;
+        updatedSync = true;
+    }
+    if (scs.toleranceSet) {
+        avsync.mTolerance = scs.sync.mTolerance;
+        updatedSync = true;
+    }
+    if (updatedSync) {
+        err = sync->setSyncSettings(avsync);
+    }
+
+    if (scs.frameRateSet && err == OK) {
+        err = sync->setVideoFrameRateHint(scs.frameRate);
+    }
+    if (err != OK) {
+        throwExceptionAsNecessary(env, err);
+        return (jfloat)0.f;
+    }
+
+    sp<const MediaClock> mediaClock = sync->getMediaClock();
+    if (mediaClock == NULL) {
+        return (jfloat)0.f;
+    }
+
+    return (jfloat)mediaClock->getPlaybackRate();
 }
 
-static jobject
-android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz)
-{
+static jobject android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) {
     sp<JMediaSync> sync = getMediaSync(env, thiz);
     if (sync == NULL) {
         throwExceptionAsNecessary(env, INVALID_OPERATION);
@@ -317,21 +441,25 @@
     }
 
     SyncSettings scs;
-    scs.syncSource = 0; // SYNC_SOURCE_DEFAULT
-    scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT
-    scs.tolerance = 0.f;
-    scs.frameRate = 0.f;
+    sync->getSyncSettings(&scs.sync);
+    scs.frameRate = sync->getVideoFrameRate();
 
-    // TODO: get this from mediaplayer when it supports it
-    // process_media_player_call(
-    //        env, thiz, mp->getSyncSettings(&scs), NULL, NULL);
     ALOGV("getSyncSettings: %d %d %f %f",
-            scs.syncSource, scs.audioAdjustMode, scs.tolerance, scs.frameRate);
+            scs.sync.mSource, scs.sync.mAudioAdjustMode, scs.sync.mTolerance, scs.frameRate);
+
+    // sanity check settings
+    if (scs.sync.mSource >= AVSYNC_SOURCE_MAX
+            || scs.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
+            || scs.sync.mTolerance < 0.f
+            || scs.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
 
     scs.syncSourceSet = true;
     scs.audioAdjustModeSet = true;
     scs.toleranceSet = true;
-    scs.frameRateSet = false;
+    scs.frameRateSet = scs.frameRate >= 0.f;
 
     return scs.asJobject(env, gSyncSettingsFields);
 }
@@ -359,6 +487,7 @@
     CHECK(gFields.mediaTimestampClockRateID != NULL);
 
     gSyncSettingsFields.init(env);
+    gPlaybackSettingsFields.init(env);
 }
 
 static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) {
@@ -367,21 +496,6 @@
     setMediaSync(env, thiz, sync);
 }
 
-static void android_media_MediaSync_native_setPlaybackRate(
-        JNIEnv *env, jobject thiz, jfloat rate) {
-    sp<JMediaSync> sync = getMediaSync(env, thiz);
-    if (sync == NULL) {
-        throwExceptionAsNecessary(env, INVALID_OPERATION);
-        return;
-    }
-
-    status_t err = sync->setPlaybackRate(rate);
-    if (err != NO_ERROR) {
-        throwExceptionAsNecessary(env, err);
-        return;
-    }
-}
-
 static void android_media_MediaSync_native_finalize(JNIEnv *env, jobject thiz) {
     android_media_MediaSync_release(env, thiz);
 }
@@ -416,11 +530,17 @@
 
     { "native_release", "()V", (void *)android_media_MediaSync_release },
 
-    { "native_setPlaybackRate", "(F)V", (void *)android_media_MediaSync_native_setPlaybackRate },
+    { "native_setPlaybackSettings", "(Landroid/media/PlaybackSettings;)F",
+      (void *)android_media_MediaSync_setPlaybackSettings },
 
-    { "setSyncSettings", "(Landroid/media/SyncSettings;)V", (void *)android_media_MediaSync_setSyncSettings},
+    { "getPlaybackSettings", "()Landroid/media/PlaybackSettings;",
+      (void *)android_media_MediaSync_getPlaybackSettings },
 
-    { "getSyncSettings", "()Landroid/media/SyncSettings;", (void *)android_media_MediaSync_getSyncSettings},
+    { "native_setSyncSettings", "(Landroid/media/SyncSettings;)F",
+      (void *)android_media_MediaSync_setSyncSettings },
+
+    { "getSyncSettings", "()Landroid/media/SyncSettings;",
+      (void *)android_media_MediaSync_getSyncSettings },
 
     { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize },
 };
diff --git a/media/jni/android_media_MediaSync.h b/media/jni/android_media_MediaSync.h
index cf81a72..80f5d63 100644
--- a/media/jni/android_media_MediaSync.h
+++ b/media/jni/android_media_MediaSync.h
@@ -18,11 +18,13 @@
 #define _ANDROID_MEDIA_MEDIASYNC_H_
 
 #include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSync.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
 namespace android {
 
+struct AudioPlaybackRate;
 class AudioTrack;
 struct IGraphicBufferProducer;
 struct MediaClock;
@@ -32,17 +34,21 @@
     JMediaSync();
 
     status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer);
-    status_t configureAudioTrack(
-            const sp<AudioTrack> &audioTrack, int32_t nativeSampleRateInHz);
+    status_t configureAudioTrack(const sp<AudioTrack> &audioTrack);
 
     status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
 
     status_t updateQueuedAudioData(int sizeInBytes, int64_t presentationTimeUs);
 
-    status_t setPlaybackRate(float rate);
-
     status_t getPlayTimeForPendingAudioFrames(int64_t *outTimeUs);
 
+    status_t setPlaybackSettings(const AudioPlaybackRate& rate);
+    void getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
+    status_t setSyncSettings(const AVSyncSettings& syncSettings);
+    void getSyncSettings(AVSyncSettings* syncSettings /* nonnull */);
+    status_t setVideoFrameRateHint(float rate);
+    float getVideoFrameRate();
+
     sp<const MediaClock> getMediaClock();
 
 protected:
diff --git a/media/jni/android_media_SyncSettings.cpp b/media/jni/android_media_SyncSettings.cpp
index 2f0605e..5da35e7 100644
--- a/media/jni/android_media_SyncSettings.cpp
+++ b/media/jni/android_media_SyncSettings.cpp
@@ -57,9 +57,9 @@
 }
 
 void SyncSettings::fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings) {
-    syncSource = env->GetIntField(settings, fields.sync_source);
-    audioAdjustMode = env->GetIntField(settings, fields.audio_adjust_mode);
-    tolerance = env->GetFloatField(settings, fields.tolerance);
+    sync.mSource = (AVSyncSource)env->GetIntField(settings, fields.sync_source);
+    sync.mAudioAdjustMode = (AVSyncAudioAdjustMode)env->GetIntField(settings, fields.audio_adjust_mode);
+    sync.mTolerance = env->GetFloatField(settings, fields.tolerance);
     frameRate = env->GetFloatField(settings, fields.frame_rate);
     int set = env->GetIntField(settings, fields.set);
 
@@ -74,9 +74,9 @@
     if (settings == NULL) {
         return NULL;
     }
-    env->SetIntField(settings, fields.sync_source, (jint)syncSource);
-    env->SetIntField(settings, fields.audio_adjust_mode, (jint)audioAdjustMode);
-    env->SetFloatField(settings, fields.tolerance, (jfloat)tolerance);
+    env->SetIntField(settings, fields.sync_source, (jint)sync.mSource);
+    env->SetIntField(settings, fields.audio_adjust_mode, (jint)sync.mAudioAdjustMode);
+    env->SetFloatField(settings, fields.tolerance, (jfloat)sync.mTolerance);
     env->SetFloatField(settings, fields.frame_rate, (jfloat)frameRate);
     env->SetIntField(
             settings, fields.set,
diff --git a/media/jni/android_media_SyncSettings.h b/media/jni/android_media_SyncSettings.h
index 586533f..23530db 100644
--- a/media/jni/android_media_SyncSettings.h
+++ b/media/jni/android_media_SyncSettings.h
@@ -19,13 +19,12 @@
 
 #include "jni.h"
 
+#include <media/stagefright/MediaSync.h>
+
 namespace android {
 
 struct SyncSettings {
-    // keep this here until it is implemented
-    int syncSource;
-    int audioAdjustMode;
-    float tolerance;
+    AVSyncSettings sync;
     float frameRate;
 
     bool syncSourceSet;
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index ddb01a0..0521833 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -27,18 +27,16 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
-    if (NULL == bm) {
-        return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
-    }
+    SkBitmap bm;
+    GraphicsJNI::getSkBitmap(env, jbitmap, &bm);
 
     if (info) {
-        info->width     = bm->width();
-        info->height    = bm->height();
-        info->stride    = bm->rowBytes();
+        info->width     = bm.width();
+        info->height    = bm.height();
+        info->stride    = bm.rowBytes();
         info->flags     = 0;
 
-        switch (bm->colorType()) {
+        switch (bm.colorType()) {
             case kN32_SkColorType:
                 info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
                 break;
@@ -64,17 +62,18 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
-    if (NULL == bm) {
+    SkPixelRef* pixelRef = GraphicsJNI::getSkPixelRef(env, jbitmap);
+    if (!pixelRef) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
 
-    bm->lockPixels();
-    void* addr = bm->getPixels();
+    pixelRef->lockPixels();
+    void* addr = pixelRef->pixels();
     if (NULL == addr) {
-        bm->unlockPixels();
+        pixelRef->unlockPixels();
         return ANDROID_BITMAP_RESULT_ALLOCATION_FAILED;
     }
+    pixelRef->ref();
 
     if (addrPtr) {
         *addrPtr = addr;
@@ -87,8 +86,8 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
-    if (NULL == bm) {
+    SkPixelRef* pixelRef = GraphicsJNI::getSkPixelRef(env, jbitmap);
+    if (!pixelRef) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
 
@@ -96,9 +95,11 @@
     // bitmaps.  Note that this will slow down read-only accesses to the
     // bitmaps, but the NDK methods are primarily intended to be used for
     // writes.
-    bm->notifyPixelsChanged();
+    pixelRef->notifyPixelsChanged();
 
-    bm->unlockPixels();
+    pixelRef->unlockPixels();
+    pixelRef->unref();
+
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f383a52..f3a2912 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -752,22 +752,22 @@
     <!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
     <string name="camera_hint">Swipe left for camera</string>
 
-    <!-- Interruption level: None. [CHAR LIMIT=20] -->
+    <!-- Interruption level: None. [CHAR LIMIT=40] -->
     <string name="interruption_level_none">Total silence</string>
 
-    <!-- Interruption level: Priority. [CHAR LIMIT=20] -->
+    <!-- Interruption level: Priority. [CHAR LIMIT=40] -->
     <string name="interruption_level_priority">Priority only</string>
 
-    <!-- Interruption level: Alarms only. [CHAR LIMIT=20] -->
+    <!-- Interruption level: Alarms only. [CHAR LIMIT=40] -->
     <string name="interruption_level_alarms">Alarms only</string>
 
-    <!-- Interruption level: None.  Optimized for narrow two-line display. [CHAR LIMIT=20] -->
+    <!-- Interruption level: None.  Optimized for narrow two-line display. [CHAR LIMIT=40] -->
     <string name="interruption_level_none_twoline">Total\nsilence</string>
 
-    <!-- Interruption level: Priority.  Optimized for narrow two-line display. [CHAR LIMIT=20] -->
+    <!-- Interruption level: Priority.  Optimized for narrow two-line display. [CHAR LIMIT=40] -->
     <string name="interruption_level_priority_twoline">Priority\nonly</string>
 
-    <!-- Interruption level: Alarms only.  Optimized for narrow two-line display. [CHAR LIMIT=20] -->
+    <!-- Interruption level: Alarms only.  Optimized for narrow two-line display. [CHAR LIMIT=40] -->
     <string name="interruption_level_alarms_twoline">Alarms\nonly</string>
 
     <!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=40]-->
diff --git a/rs/java/android/renderscript/ScriptIntrinsicBLAS.java b/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
index a387aab..5e28d3f 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
@@ -1012,7 +1012,7 @@
             }
         } else {
             if (A != null) {
-                if (TransA != NO_TRANSPOSE) {
+                if (TransA == TRANSPOSE || TransA == CONJ_TRANSPOSE) {
                     aN = A.getType().getY();
                     aM = A.getType().getX();
                 } else {
@@ -1021,7 +1021,7 @@
                 }
             }
             if (B != null) {
-                if (TransB != NO_TRANSPOSE) {
+                if (TransB == TRANSPOSE || TransB == CONJ_TRANSPOSE) {
                     bN = B.getType().getY();
                     bM = B.getType().getX();
                 } else {
@@ -1272,7 +1272,7 @@
         validateUplo(Uplo);
         validateSYR2K(Element.F32(mRS), Trans, A, B, C);
         int K = -1;
-        if (Trans == TRANSPOSE) {
+        if (Trans != NO_TRANSPOSE) {
             K = A.getType().getY();
         } else {
             K = A.getType().getX();
@@ -1283,34 +1283,34 @@
         validateUplo(Uplo);
         validateSYR2K(Element.F64(mRS), Trans, A, B, C);
         int K = -1;
-        if (Trans == TRANSPOSE) {
+        if (Trans != NO_TRANSPOSE) {
             K = A.getType().getY();
         } else {
             K = A.getType().getX();
         }
-        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), B.getID(mRS), beta, C.getID(mRS), 0, 0, 0, 0);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), B.getID(mRS), beta, C.getID(mRS), 0, 0, 0, 0);
     }
     public void CSYR2K(@Uplo int Uplo, @Transpose int Trans, Float2 alpha, Allocation A, Allocation B, Float2 beta, Allocation C) {
         validateUplo(Uplo);
         validateSYR2K(Element.F32_2(mRS), Trans, A, B, C);
         int K = -1;
-        if (Trans == TRANSPOSE) {
+        if (Trans != NO_TRANSPOSE) {
             K = A.getType().getY();
         } else {
             K = A.getType().getX();
         }
-        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_csyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
     }
     public void ZSYR2K(@Uplo int Uplo, @Transpose int Trans, Double2 alpha, Allocation A, Allocation B, Double2 beta, Allocation C) {
         validateUplo(Uplo);
         validateSYR2K(Element.F64_2(mRS), Trans, A, B, C);
         int K = -1;
-        if (Trans == TRANSPOSE) {
+        if (Trans != NO_TRANSPOSE) {
             K = A.getType().getY();
         } else {
             K = A.getType().getX();
         }
-        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zsyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
     }
 
     static void validateTRMM(Element e, @Side int Side, @Transpose int TransA, Allocation A, Allocation B) {
@@ -1351,21 +1351,21 @@
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRMM(Element.F64(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
-                                        alpha, A.getID(mRS), B.getID(mRS), 0.f, 0, 0, 0, 0, 0);
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+                                        alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
     }
     public void CTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Float2 alpha, Allocation A, Allocation B) {
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRMM(Element.F32_2(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                          alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
     }
     public void ZTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Double2 alpha, Allocation A, Allocation B) {
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRMM(Element.F64_2(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                    alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
     }
 
@@ -1409,21 +1409,21 @@
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRSM(Element.F64(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                         alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
     }
     public void CTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Float2 alpha, Allocation A, Allocation B) {
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRSM(Element.F32_2(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                          alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
     }
     public void ZTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Double2 alpha, Allocation A, Allocation B) {
         validateUplo(Uplo);
         validateDiag(Diag);
         validateTRSM(Element.F64_2(mRS), Side, TransA, A, B);
-        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+        mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
                                    alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
     }
 
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index cbe87fc..5ef807d 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -526,7 +526,7 @@
     call.alpha.c.r = alphaX;
     call.alpha.c.i = alphaY;
     call.beta.c.r = betaX;
-    call.beta.c.r = betaY;
+    call.beta.c.i = betaY;
     call.incX = incX;
     call.incY = incY;
     call.KL = KL;
@@ -561,7 +561,7 @@
     call.alpha.z.r = alphaX;
     call.alpha.z.i = alphaY;
     call.beta.z.r = betaX;
-    call.beta.z.r = betaY;
+    call.beta.z.i = betaY;
     call.incX = incX;
     call.incY = incY;
     call.KL = KL;
@@ -1102,9 +1102,8 @@
 nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip,
                             jobject jbitmap, jint usage)
 {
-    SkBitmap const * nativeBitmap =
-            GraphicsJNI::getSkBitmap(_env, jbitmap);
-    const SkBitmap& bitmap(*nativeBitmap);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
@@ -1119,9 +1118,8 @@
 nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type,
                                         jint mip, jobject jbitmap, jint usage)
 {
-    SkBitmap const * nativeBitmap =
-            GraphicsJNI::getSkBitmap(_env, jbitmap);
-    const SkBitmap& bitmap(*nativeBitmap);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
@@ -1136,9 +1134,8 @@
 nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip,
                                 jobject jbitmap, jint usage)
 {
-    SkBitmap const * nativeBitmap =
-            GraphicsJNI::getSkBitmap(_env, jbitmap);
-    const SkBitmap& bitmap(*nativeBitmap);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
@@ -1152,9 +1149,8 @@
 static void
 nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
 {
-    SkBitmap const * nativeBitmap =
-            GraphicsJNI::getSkBitmap(_env, jbitmap);
-    const SkBitmap& bitmap(*nativeBitmap);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
     int w = bitmap.width();
     int h = bitmap.height();
 
@@ -1169,9 +1165,8 @@
 static void
 nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
 {
-    SkBitmap const * nativeBitmap =
-            GraphicsJNI::getSkBitmap(_env, jbitmap);
-    const SkBitmap& bitmap(*nativeBitmap);
+    SkBitmap bitmap;
+    GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
 
     bitmap.lockPixels();
     void* ptr = bitmap.getPixels();
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index ef82bb7..1019faa 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -48,6 +48,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
 
 import java.io.FileDescriptor;
@@ -443,6 +444,16 @@
     /** Internal death rec list */
     Map<IBinder, ClientDeathRecipient> mBleApps = new HashMap<IBinder, ClientDeathRecipient>();
 
+    @Override
+    public boolean isBleScanAlwaysAvailable() {
+        try {
+            return (Settings.Global.getInt(mContentResolver,
+                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0;
+        } catch (SettingNotFoundException e) {
+        }
+        return false;
+    }
+
     public int updateBleAppCount(IBinder token, boolean enable) {
         if (enable) {
             ClientDeathRecipient r = mBleApps.get(token);
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 6b5908d..ed8519a 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -16,14 +16,15 @@
 
 package com.android.server.fingerprint;
 
+import android.app.AppOpsManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.RemoteException;
-import android.util.ArrayMap;
 import android.util.Slog;
 
 import com.android.server.SystemService;
@@ -39,6 +40,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -55,6 +57,8 @@
     private ClientMonitor mEnrollClient = null;
     private ClientMonitor mRemoveClient = null;
 
+    private final AppOpsManager mAppOps;
+
     private static final int MSG_NOTIFY = 10;
 
     private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
@@ -96,6 +100,7 @@
     public FingerprintService(Context context) {
         super(context);
         mContext = context;
+        mAppOps = context.getSystemService(AppOpsManager.class);
         nativeInit(Looper.getMainLooper().getQueue(), this);
     }
 
@@ -361,6 +366,13 @@
                 "Must have " + permission + " permission.");
     }
 
+    private boolean canUserFingerPrint(String opPackageName) {
+        checkPermission(USE_FINGERPRINT);
+
+        return mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, Binder.getCallingUid(),
+                opPackageName) == AppOpsManager.MODE_ALLOWED;
+    }
+
     private class ClientMonitor implements IBinder.DeathRecipient {
         IBinder token;
         IFingerprintServiceReceiver receiver;
@@ -522,8 +534,11 @@
         @Override
         // Binder call
         public void authenticate(final IBinder token, final long opId, final int groupId,
-                final IFingerprintServiceReceiver receiver, final int flags) {
+                final IFingerprintServiceReceiver receiver, final int flags, String opPackageName) {
             checkPermission(USE_FINGERPRINT);
+            if (!canUserFingerPrint(opPackageName)) {
+                return;
+            }
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -535,8 +550,10 @@
         @Override
 
         // Binder call
-        public void cancelAuthentication(final IBinder token) {
-            checkPermission(USE_FINGERPRINT);
+        public void cancelAuthentication(final IBinder token, String opPackageName) {
+            if (!canUserFingerPrint(opPackageName)) {
+                return;
+            }
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -561,8 +578,10 @@
 
         @Override
         // Binder call
-        public boolean isHardwareDetected(long deviceId) {
-            checkPermission(USE_FINGERPRINT);
+        public boolean isHardwareDetected(long deviceId, String opPackageName) {
+            if (!canUserFingerPrint(opPackageName)) {
+                return false;
+            }
             return mHalDeviceId != 0; // TODO
         }
 
@@ -580,21 +599,27 @@
 
         @Override
         // Binder call
-        public List<Fingerprint> getEnrolledFingerprints(int groupId) {
-            checkPermission(USE_FINGERPRINT);
+        public List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName) {
+            if (!canUserFingerPrint(opPackageName)) {
+                return Collections.emptyList();
+            }
             return FingerprintService.this.getEnrolledFingerprints(groupId);
         }
 
         @Override
         // Binder call
-        public boolean hasEnrolledFingerprints(int groupId) {
-            checkPermission(USE_FINGERPRINT);
+        public boolean hasEnrolledFingerprints(int groupId, String opPackageName) {
+            if (!canUserFingerPrint(opPackageName)) {
+                return false;
+            }
             return FingerprintService.this.hasEnrolledFingerprints(groupId);
         }
 
         @Override
-        public long getAuthenticatorId() {
-            checkPermission(USE_FINGERPRINT);
+        public long getAuthenticatorId(String opPackageName) {
+            if (!canUserFingerPrint(opPackageName)) {
+                return 0;
+            }
             return nativeGetAuthenticatorId();
         }
     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5536d4d..adc3a7d 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -285,6 +285,9 @@
     // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
     long[] mSafeModeEnabledVibePattern;
 
+    // Vibrator pattern for haptic feedback of a stylus button press.
+    long[] mStylusButtonPressVibePattern;
+
     /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
     boolean mEnableShiftMenuBugReports = false;
 
@@ -1436,6 +1439,8 @@
                 com.android.internal.R.array.config_safeModeDisabledVibePattern);
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
+        mStylusButtonPressVibePattern = getLongIntArray(mContext.getResources(),
+                com.android.internal.R.array.config_stylusButtonPressVibePattern);
 
         mScreenshotChordEnabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableScreenshotChord);
@@ -6164,6 +6169,9 @@
             case HapticFeedbackConstants.SAFE_MODE_ENABLED:
                 pattern = mSafeModeEnabledVibePattern;
                 break;
+            case HapticFeedbackConstants.STYLUS_BUTTON_PRESS:
+                pattern = mStylusButtonPressVibePattern;
+                break;
             default:
                 return false;
         }
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index ad1d0f5..3d8905d 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -64,7 +64,7 @@
 static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject,
         jobject graphicBuffer, jobject bitmapHandle) {
 
-    SkBitmap& bitmap = *GraphicsJNI::getSkBitmap(env, bitmapHandle);
+    SkBitmap& bitmap = *GraphicsJNI::getSkBitmapDeprecated(env, bitmapHandle);
     SkAutoLockPixels alp(bitmap);
 
     // The goal of this method is to copy the bitmap into the GraphicBuffer
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index d92c0c7..9273939 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -19,10 +19,12 @@
 import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 
 import java.lang.String;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -608,7 +610,7 @@
     private final List<String> mChildrenIds = new ArrayList<>();
     private final List<Call> mChildren = new ArrayList<>();
     private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
-    private final List<Callback> mCallbacks = new CopyOnWriteArrayList<>();
+    private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
     private final List<Call> mConferenceableCalls = new ArrayList<>();
     private final List<Call> mUnmodifiableConferenceableCalls =
             Collections.unmodifiableList(mConferenceableCalls);
@@ -850,7 +852,20 @@
      * @param callback A {@code Callback}.
      */
     public void registerCallback(Callback callback) {
-        mCallbacks.add(callback);
+        registerCallback(callback, new Handler());
+    }
+
+    /**
+     * Registers a callback to this {@code Call}.
+     *
+     * @param callback A {@code Callback}.
+     * @param handler A handler which command and status changes will be delivered to.
+     */
+    public void registerCallback(Callback callback, Handler handler) {
+        unregisterCallback(callback);
+        if (callback != null && handler != null) {
+            mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
+        }
     }
 
     /**
@@ -860,7 +875,12 @@
      */
     public void unregisterCallback(Callback callback) {
         if (callback != null) {
-            mCallbacks.remove(callback);
+            for (CallbackRecord<Callback> record : mCallbackRecords) {
+                if (record.getCallback() == callback) {
+                    mCallbackRecords.remove(record);
+                    break;
+                }
+            }
         }
     }
 
@@ -1021,57 +1041,120 @@
         }
     }
 
-    private void fireStateChanged(int newState) {
-        for (Callback callback : mCallbacks) {
-            callback.onStateChanged(this, newState);
+    private void fireStateChanged(final int newState) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onStateChanged(call, newState);
+                }
+            });
         }
     }
 
-    private void fireParentChanged(Call newParent) {
-        for (Callback callback : mCallbacks) {
-            callback.onParentChanged(this, newParent);
+    private void fireParentChanged(final Call newParent) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onParentChanged(call, newParent);
+                }
+            });
         }
     }
 
-    private void fireChildrenChanged(List<Call> children) {
-        for (Callback callback : mCallbacks) {
-            callback.onChildrenChanged(this, children);
+    private void fireChildrenChanged(final List<Call> children) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onChildrenChanged(call, children);
+                }
+            });
         }
     }
 
-    private void fireDetailsChanged(Details details) {
-        for (Callback callback : mCallbacks) {
-            callback.onDetailsChanged(this, details);
+    private void fireDetailsChanged(final Details details) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onDetailsChanged(call, details);
+                }
+            });
         }
     }
 
-    private void fireCannedTextResponsesLoaded(List<String> cannedTextResponses) {
-        for (Callback callback : mCallbacks) {
-            callback.onCannedTextResponsesLoaded(this, cannedTextResponses);
+    private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
+                }
+            });
         }
     }
 
-    private void fireVideoCallChanged(InCallService.VideoCall videoCall) {
-        for (Callback callback : mCallbacks) {
-            callback.onVideoCallChanged(this, videoCall);
+    private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onVideoCallChanged(call, videoCall);
+                }
+            });
         }
     }
 
-    private void firePostDialWait(String remainingPostDialSequence) {
-        for (Callback callback : mCallbacks) {
-            callback.onPostDialWait(this, remainingPostDialSequence);
+    private void firePostDialWait(final String remainingPostDialSequence) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onPostDialWait(call, remainingPostDialSequence);
+                }
+            });
         }
     }
 
     private void fireCallDestroyed() {
-        for (Callback callback : mCallbacks) {
-            callback.onCallDestroyed(this);
+        for (CallbackRecord<Callback> record: mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onCallDestroyed(call);
+                }
+            });
         }
     }
 
     private void fireConferenceableCallsChanged() {
-        for (Callback callback : mCallbacks) {
-            callback.onConferenceableCallsChanged(this, mUnmodifiableConferenceableCalls);
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
+                }
+            });
         }
     }
 }
diff --git a/telecomm/java/android/telecom/CallbackRecord.java b/telecomm/java/android/telecom/CallbackRecord.java
new file mode 100644
index 0000000..1a81925
--- /dev/null
+++ b/telecomm/java/android/telecom/CallbackRecord.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.telecom;
+
+import android.os.Handler;
+
+
+/**
+ * This class is used to associate a generic callback of type T with a handler to which commands and
+ * status updates will be delivered to.
+ *
+ * @hide
+ */
+class CallbackRecord<T> {
+    private final T mCallback;
+    private final Handler mHandler;
+
+    public CallbackRecord(T callback, Handler handler) {
+        mCallback = callback;
+        mHandler = handler;
+    }
+
+    public T getCallback() {
+        return mCallback;
+    }
+
+    public Handler getHandler() {
+        return mHandler;
+    }
+}
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 2c8415a..3cb4e87 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -362,6 +362,9 @@
      */
     public static abstract class VideoCall {
 
+        /** @hide */
+        public abstract void destroy();
+
         /**
          * Registers a callback to receive commands and state changes for video calls.
          *
@@ -370,9 +373,17 @@
         public abstract void registerCallback(VideoCall.Callback callback);
 
         /**
+         * Registers a callback to receive commands and state changes for video calls.
+         *
+         * @param callback The video call callback.
+         * @param handler A handler which commands and status changes will be delivered to.
+         */
+        public abstract void registerCallback(VideoCall.Callback callback, Handler handler);
+
+        /**
          * Clears the video call listener set via {@link #registerCallback}.
          */
-        public abstract void unregisterCallback();
+        public abstract void unregisterCallback(VideoCall.Callback callback);
 
         /**
          * Sets the camera to be used for video recording in a video call.
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 3d9acda..4cdfd2e 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -125,7 +125,7 @@
 
         InCallService.VideoCall videoCall = call.getVideoCall();
         if (videoCall != null) {
-            videoCall.unregisterCallback();
+            videoCall.destroy();
         }
         fireCallRemoved(call);
     }
@@ -174,7 +174,7 @@
         for (Call call : mCalls) {
             InCallService.VideoCall videoCall = call.getVideoCall();
             if (videoCall != null) {
-                videoCall.unregisterCallback();
+                videoCall.destroy();
             }
             if (call.getState() != Call.STATE_DISCONNECTED) {
                 call.internalSetDisconnected();
diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java
index fba3ee3..a76bf59 100644
--- a/telecomm/java/android/telecom/RemoteConference.java
+++ b/telecomm/java/android/telecom/RemoteConference.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.telecom.IConnectionService;
 
+import android.os.Handler;
 import android.os.RemoteException;
 
 import java.util.ArrayList;
@@ -49,7 +50,7 @@
     private final String mId;
     private final IConnectionService mConnectionService;
 
-    private final Set<Callback> mCallbacks = new CopyOnWriteArraySet<>();
+    private final Set<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArraySet<>();
     private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();
     private final List<RemoteConnection> mUnmodifiableChildConnections =
             Collections.unmodifiableList(mChildConnections);
@@ -77,13 +78,20 @@
         for (RemoteConnection connection : mChildConnections) {
             connection.setConference(null);
         }
-        for (Callback c : mCallbacks) {
-            c.onDestroyed(this);
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final RemoteConference conference = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onDestroyed(conference);
+                }
+            });
         }
     }
 
     /** {@hide} */
-    void setState(int newState) {
+    void setState(final int newState) {
         if (newState != Connection.STATE_ACTIVE &&
                 newState != Connection.STATE_HOLDING &&
                 newState != Connection.STATE_DISCONNECTED) {
@@ -93,42 +101,71 @@
         }
 
         if (mState != newState) {
-            int oldState = mState;
+            final int oldState = mState;
             mState = newState;
-            for (Callback c : mCallbacks) {
-                c.onStateChanged(this, oldState, newState);
+            for (CallbackRecord<Callback> record : mCallbackRecords) {
+                final RemoteConference conference = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onStateChanged(conference, oldState, newState);
+                    }
+                });
             }
         }
     }
 
     /** {@hide} */
-    void addConnection(RemoteConnection connection) {
+    void addConnection(final RemoteConnection connection) {
         if (!mChildConnections.contains(connection)) {
             mChildConnections.add(connection);
             connection.setConference(this);
-            for (Callback c : mCallbacks) {
-                c.onConnectionAdded(this, connection);
+            for (CallbackRecord<Callback> record : mCallbackRecords) {
+                final RemoteConference conference = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onConnectionAdded(conference, connection);
+                    }
+                });
             }
         }
     }
 
     /** {@hide} */
-    void removeConnection(RemoteConnection connection) {
+    void removeConnection(final RemoteConnection connection) {
         if (mChildConnections.contains(connection)) {
             mChildConnections.remove(connection);
             connection.setConference(null);
-            for (Callback c : mCallbacks) {
-                c.onConnectionRemoved(this, connection);
+            for (CallbackRecord<Callback> record : mCallbackRecords) {
+                final RemoteConference conference = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onConnectionRemoved(conference, connection);
+                    }
+                });
             }
         }
     }
 
     /** {@hide} */
-    void setConnectionCapabilities(int connectionCapabilities) {
+    void setConnectionCapabilities(final int connectionCapabilities) {
         if (mConnectionCapabilities != connectionCapabilities) {
             mConnectionCapabilities = connectionCapabilities;
-            for (Callback c : mCallbacks) {
-                c.onConnectionCapabilitiesChanged(this, mConnectionCapabilities);
+            for (CallbackRecord<Callback> record : mCallbackRecords) {
+                final RemoteConference conference = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onConnectionCapabilitiesChanged(
+                                conference, mConnectionCapabilities);
+                    }
+                });
             }
         }
     }
@@ -137,18 +174,33 @@
     void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) {
         mConferenceableConnections.clear();
         mConferenceableConnections.addAll(conferenceableConnections);
-        for (Callback c : mCallbacks) {
-            c.onConferenceableConnectionsChanged(this, mUnmodifiableConferenceableConnections);
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final RemoteConference conference = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onConferenceableConnectionsChanged(
+                            conference, mUnmodifiableConferenceableConnections);
+                }
+            });
         }
     }
 
     /** {@hide} */
-    void setDisconnected(DisconnectCause disconnectCause) {
+    void setDisconnected(final DisconnectCause disconnectCause) {
         if (mState != Connection.STATE_DISCONNECTED) {
             mDisconnectCause = disconnectCause;
             setState(Connection.STATE_DISCONNECTED);
-            for (Callback c : mCallbacks) {
-                c.onDisconnected(this, disconnectCause);
+            for (CallbackRecord<Callback> record : mCallbackRecords) {
+                final RemoteConference conference = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onDisconnected(conference, disconnectCause);
+                    }
+                });
             }
         }
     }
@@ -239,10 +291,24 @@
     }
 
     public final void registerCallback(Callback callback) {
-        mCallbacks.add(callback);
+        registerCallback(callback, new Handler());
+    }
+
+    public final void registerCallback(Callback callback, Handler handler) {
+        unregisterCallback(callback);
+        if (callback != null && handler != null) {
+            mCallbackRecords.add(new CallbackRecord(callback, handler));
+        }
     }
 
     public final void unregisterCallback(Callback callback) {
-        mCallbacks.remove(callback);
+        if (callback != null) {
+            for (CallbackRecord<Callback> record : mCallbackRecords) {
+                if (record.getCallback() == callback) {
+                    mCallbackRecords.remove(record);
+                    break;
+                }
+            }
+        }
     }
 }
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 4ecfd50..1493b20 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -21,6 +21,7 @@
 import com.android.internal.telecom.IVideoProvider;
 
 import android.net.Uri;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.view.Surface;
@@ -392,8 +393,8 @@
      * load factor before resizing, 1 means we only expect a single thread to
      * access the map so make only a single shard
      */
-    private final Set<Callback> mCallbacks = Collections.newSetFromMap(
-            new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1));
+    private final Set<CallbackRecord> mCallbackRecords = Collections.newSetFromMap(
+            new ConcurrentHashMap<CallbackRecord, Boolean>(8, 0.9f, 1));
     private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>();
     private final List<RemoteConnection> mUnmodifiableconferenceableConnections =
             Collections.unmodifiableList(mConferenceableConnections);
@@ -470,7 +471,20 @@
      * @param callback A {@code Callback}.
      */
     public void registerCallback(Callback callback) {
-        mCallbacks.add(callback);
+        registerCallback(callback, new Handler());
+    }
+
+    /**
+     * Adds a callback to this {@code RemoteConnection}.
+     *
+     * @param callback A {@code Callback}.
+     * @param handler A {@code Handler} which command and status changes will be delivered to.
+     */
+    public void registerCallback(Callback callback, Handler handler) {
+        unregisterCallback(callback);
+        if (callback != null && handler != null) {
+            mCallbackRecords.add(new CallbackRecord(callback, handler));
+        }
     }
 
     /**
@@ -480,7 +494,12 @@
      */
     public void unregisterCallback(Callback callback) {
         if (callback != null) {
-            mCallbacks.remove(callback);
+            for (CallbackRecord record : mCallbackRecords) {
+                if (record.getCallback() == callback) {
+                    mCallbackRecords.remove(record);
+                    break;
+                }
+            }
         }
     }
 
@@ -800,11 +819,18 @@
     /**
      * @hide
      */
-    void setState(int state) {
+    void setState(final int state) {
         if (mState != state) {
             mState = state;
-            for (Callback c: mCallbacks) {
-                c.onStateChanged(this, state);
+            for (CallbackRecord record: mCallbackRecords) {
+                final RemoteConnection connection = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onStateChanged(connection, state);
+                    }
+                });
             }
         }
     }
@@ -812,13 +838,20 @@
     /**
      * @hide
      */
-    void setDisconnected(DisconnectCause disconnectCause) {
+    void setDisconnected(final DisconnectCause disconnectCause) {
         if (mState != Connection.STATE_DISCONNECTED) {
             mState = Connection.STATE_DISCONNECTED;
             mDisconnectCause = disconnectCause;
 
-            for (Callback c : mCallbacks) {
-                c.onDisconnected(this, mDisconnectCause);
+            for (CallbackRecord record : mCallbackRecords) {
+                final RemoteConnection connection = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onDisconnected(connection, disconnectCause);
+                    }
+                });
             }
         }
     }
@@ -826,11 +859,18 @@
     /**
      * @hide
      */
-    void setRingbackRequested(boolean ringback) {
+    void setRingbackRequested(final boolean ringback) {
         if (mRingbackRequested != ringback) {
             mRingbackRequested = ringback;
-            for (Callback c : mCallbacks) {
-                c.onRingbackRequested(this, ringback);
+            for (CallbackRecord record : mCallbackRecords) {
+                final RemoteConnection connection = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onRingbackRequested(connection, ringback);
+                    }
+                });
             }
         }
     }
@@ -838,10 +878,17 @@
     /**
      * @hide
      */
-    void setConnectionCapabilities(int connectionCapabilities) {
+    void setConnectionCapabilities(final int connectionCapabilities) {
         mConnectionCapabilities = connectionCapabilities;
-        for (Callback c : mCallbacks) {
-            c.onConnectionCapabilitiesChanged(this, connectionCapabilities);
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onConnectionCapabilitiesChanged(connection, connectionCapabilities);
+                }
+            });
         }
     }
 
@@ -849,17 +896,24 @@
      * @hide
      */
     void setDestroyed() {
-        if (!mCallbacks.isEmpty()) {
+        if (!mCallbackRecords.isEmpty()) {
             // Make sure that the callbacks are notified that the call is destroyed first.
             if (mState != Connection.STATE_DISCONNECTED) {
                 setDisconnected(
                         new DisconnectCause(DisconnectCause.ERROR, "Connection destroyed."));
             }
 
-            for (Callback c : mCallbacks) {
-                c.onDestroyed(this);
+            for (CallbackRecord record : mCallbackRecords) {
+                final RemoteConnection connection = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onDestroyed(connection);
+                    }
+                });
             }
-            mCallbacks.clear();
+            mCallbackRecords.clear();
 
             mConnected = false;
         }
@@ -868,90 +922,162 @@
     /**
      * @hide
      */
-    void setPostDialWait(String remainingDigits) {
-        for (Callback c : mCallbacks) {
-            c.onPostDialWait(this, remainingDigits);
+    void setPostDialWait(final String remainingDigits) {
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onPostDialWait(connection, remainingDigits);
+                }
+            });
         }
     }
 
     /**
      * @hide
      */
-    void onPostDialChar(char nextChar) {
-        for (Callback c : mCallbacks) {
-            c.onPostDialChar(this, nextChar);
+    void onPostDialChar(final char nextChar) {
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onPostDialWait(connection, String.valueOf(nextChar));
+                }
+            });
         }
     }
 
     /**
      * @hide
      */
-    void setVideoState(int videoState) {
+    void setVideoState(final int videoState) {
         mVideoState = videoState;
-        for (Callback c : mCallbacks) {
-            c.onVideoStateChanged(this, videoState);
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onVideoStateChanged(connection, videoState);
+                }
+            });
         }
     }
 
     /**
      * @hide
      */
-    void setVideoProvider(VideoProvider videoProvider) {
+    void setVideoProvider(final VideoProvider videoProvider) {
         mVideoProvider = videoProvider;
-        for (Callback c : mCallbacks) {
-            c.onVideoProviderChanged(this, videoProvider);
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onVideoProviderChanged(connection, videoProvider);
+                }
+            });
         }
     }
 
     /** @hide */
-    void setIsVoipAudioMode(boolean isVoip) {
+    void setIsVoipAudioMode(final boolean isVoip) {
         mIsVoipAudioMode = isVoip;
-        for (Callback c : mCallbacks) {
-            c.onVoipAudioChanged(this, isVoip);
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onVoipAudioChanged(connection, isVoip);
+                }
+            });
         }
     }
 
     /** @hide */
-    void setStatusHints(StatusHints statusHints) {
+    void setStatusHints(final StatusHints statusHints) {
         mStatusHints = statusHints;
-        for (Callback c : mCallbacks) {
-            c.onStatusHintsChanged(this, statusHints);
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onStatusHintsChanged(connection, statusHints);
+                }
+            });
         }
     }
 
     /** @hide */
-    void setAddress(Uri address, int presentation) {
+    void setAddress(final Uri address, final int presentation) {
         mAddress = address;
         mAddressPresentation = presentation;
-        for (Callback c : mCallbacks) {
-            c.onAddressChanged(this, address, presentation);
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onAddressChanged(connection, address, presentation);
+                }
+            });
         }
     }
 
     /** @hide */
-    void setCallerDisplayName(String callerDisplayName, int presentation) {
+    void setCallerDisplayName(final String callerDisplayName, final int presentation) {
         mCallerDisplayName = callerDisplayName;
         mCallerDisplayNamePresentation = presentation;
-        for (Callback c : mCallbacks) {
-            c.onCallerDisplayNameChanged(this, callerDisplayName, presentation);
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onCallerDisplayNameChanged(
+                            connection, callerDisplayName, presentation);
+                }
+            });
         }
     }
 
     /** @hide */
-    void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) {
+    void setConferenceableConnections(final List<RemoteConnection> conferenceableConnections) {
         mConferenceableConnections.clear();
         mConferenceableConnections.addAll(conferenceableConnections);
-        for (Callback c : mCallbacks) {
-            c.onConferenceableConnectionsChanged(this, mUnmodifiableconferenceableConnections);
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onConferenceableConnectionsChanged(
+                            connection, mUnmodifiableconferenceableConnections);
+                }
+            });
         }
     }
 
     /** @hide */
-    void setConference(RemoteConference conference) {
+    void setConference(final RemoteConference conference) {
         if (mConference != conference) {
             mConference = conference;
-            for (Callback c : mCallbacks) {
-                c.onConferenceChanged(this, conference);
+            for (CallbackRecord record : mCallbackRecords) {
+                final RemoteConnection connection = this;
+                final Callback callback = record.getCallback();
+                record.getHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        callback.onConferenceChanged(connection, conference);
+                    }
+                });
             }
         }
     }
@@ -968,4 +1094,22 @@
     public static RemoteConnection failure(DisconnectCause disconnectCause) {
         return new RemoteConnection(disconnectCause);
     }
+
+    private static final class CallbackRecord extends Callback {
+        private final Callback mCallback;
+        private final Handler mHandler;
+
+        public CallbackRecord(Callback callback, Handler handler) {
+            mCallback = callback;
+            mHandler = handler;
+        }
+
+        public Callback getCallback() {
+            return mCallback;
+        }
+
+        public Handler getHandler() {
+            return mHandler;
+        }
+    }
 }
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 8d6bda8..1431eb8 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -921,7 +921,7 @@
     public void silenceRinger() {
         try {
             if (isServiceConnected()) {
-                getTelecomService().silenceRinger();
+                getTelecomService().silenceRinger(mContext.getOpPackageName());
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelecomService#silenceRinger", e);
@@ -1029,7 +1029,7 @@
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
-                return service.handlePinMmi(dialString);
+                return service.handlePinMmi(dialString, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#handlePinMmi", e);
             }
@@ -1053,7 +1053,8 @@
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
-                return service.handlePinMmiForPhoneAccount(accountHandle, dialString);
+                return service.handlePinMmiForPhoneAccount(accountHandle, dialString,
+                        mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#handlePinMmi", e);
             }
@@ -1071,7 +1072,7 @@
         ITelecomService service = getTelecomService();
         if (service != null && accountHandle != null) {
             try {
-                return service.getAdnUriForPhoneAccount(accountHandle);
+                return service.getAdnUriForPhoneAccount(accountHandle, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#getAdnUriForPhoneAccount", e);
             }
@@ -1089,7 +1090,7 @@
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
-                service.cancelMissedCallsNotification();
+                service.cancelMissedCallsNotification(mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Log.e(TAG, "Error calling ITelecomService#cancelMissedCallsNotification", e);
             }
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 3779d1a..7a82c1b 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -36,13 +36,6 @@
  * {@hide}
  */
 public class VideoCallImpl extends VideoCall {
-    private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
-    private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
-    private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
-    private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
-    private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
-    private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
-    private static final int MSG_CHANGE_VIDEO_QUALITY = 7;
 
     private final IVideoProvider mVideoProvider;
     private final VideoCallListenerBinder mBinder;
@@ -61,7 +54,7 @@
     private final class VideoCallListenerBinder extends IVideoCallback.Stub {
         @Override
         public void receiveSessionModifyRequest(VideoProfile videoProfile) {
-            mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_REQUEST,
+            mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,
                     videoProfile).sendToTarget();
         }
 
@@ -72,12 +65,14 @@
             args.arg1 = status;
             args.arg2 = requestProfile;
             args.arg3 = responseProfile;
-            mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args).sendToTarget();
+            mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args)
+                    .sendToTarget();
         }
 
         @Override
         public void handleCallSessionEvent(int event) {
-            mHandler.obtainMessage(MSG_HANDLE_CALL_SESSION_EVENT, event).sendToTarget();
+            mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event)
+                    .sendToTarget();
         }
 
         @Override
@@ -85,28 +80,42 @@
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = width;
             args.arg2 = height;
-            mHandler.obtainMessage(MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
+            mHandler.obtainMessage(MessageHandler.MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
         }
 
         @Override
         public void changeVideoQuality(int videoQuality) {
-            mHandler.obtainMessage(MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0).sendToTarget();
+            mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0)
+                    .sendToTarget();
         }
 
         @Override
         public void changeCallDataUsage(long dataUsage) {
-            mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, dataUsage).sendToTarget();
+            mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage)
+                    .sendToTarget();
         }
 
         @Override
         public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
-            mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES,
+            mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
                     cameraCapabilities).sendToTarget();
         }
     }
 
     /** Default handler used to consolidate binder method calls onto a single thread. */
-    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+    private final class MessageHandler extends Handler {
+        private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
+        private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
+        private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
+        private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
+        private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
+        private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
+        private static final int MSG_CHANGE_VIDEO_QUALITY = 7;
+
+        public MessageHandler(Looper looper) {
+            super(looper);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             if (mCallback == null) {
@@ -160,7 +169,8 @@
         }
     };
 
-    /** {@hide} */
+    private Handler mHandler;
+
     VideoCallImpl(IVideoProvider videoProvider) throws RemoteException {
         mVideoProvider = videoProvider;
         mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
@@ -169,13 +179,31 @@
         mVideoProvider.addVideoCallback(mBinder);
     }
 
-    /** {@inheritDoc} */
-    public void registerCallback(VideoCall.Callback callback) {
-        mCallback = callback;
+    public void destroy() {
+        unregisterCallback(mCallback);
     }
 
     /** {@inheritDoc} */
-    public void unregisterCallback() {
+    public void registerCallback(VideoCall.Callback callback) {
+        registerCallback(callback, null);
+    }
+
+    /** {@inheritDoc} */
+    public void registerCallback(VideoCall.Callback callback, Handler handler) {
+        mCallback = callback;
+        if (handler == null) {
+            mHandler = new MessageHandler(Looper.getMainLooper());
+        } else {
+            mHandler = new MessageHandler(handler.getLooper());
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void unregisterCallback(VideoCall.Callback callback) {
+        if (callback != mCallback) {
+            return;
+        }
+
         mCallback = null;
         try {
             mVideoProvider.removeVideoCallback(mBinder);
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 49f2aad..bc76f06 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -154,7 +154,7 @@
     /**
      * @see TelecomServiceImpl#silenceRinger
      */
-    void silenceRinger();
+    void silenceRinger(String callingPackage);
 
     /**
      * @see TelecomServiceImpl#isInCall
@@ -184,22 +184,23 @@
     /**
      * @see TelecomServiceImpl#cancelMissedCallsNotification
      */
-    void cancelMissedCallsNotification();
+    void cancelMissedCallsNotification(String callingPackage);
 
     /**
      * @see TelecomServiceImpl#handleMmi
      */
-    boolean handlePinMmi(String dialString);
+    boolean handlePinMmi(String dialString, String callingPackage);
 
     /**
      * @see TelecomServiceImpl#handleMmi
      */
-    boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString);
+    boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString,
+            String callingPackage);
 
     /**
      * @see TelecomServiceImpl#getAdnUriForPhoneAccount
      */
-    Uri getAdnUriForPhoneAccount(in PhoneAccountHandle accountHandle);
+    Uri getAdnUriForPhoneAccount(in PhoneAccountHandle accountHandle, String callingPackage);
 
     /**
      * @see TelecomServiceImpl#isTtySupported
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ee7f0ea..d674b31 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3703,7 +3703,7 @@
     @SystemApi
     public void silenceRinger() {
         try {
-            getTelecomService().silenceRinger();
+            getTelecomService().silenceRinger(mContext.getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelecomService#silenceRinger", e);
         }
diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
index 7f1e977..4072302 100644
--- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
@@ -164,10 +164,6 @@
                                 com.android.internal.R.styleable.Include_id, View.NO_ID);
                         final int visibility = a.getInt(
                                 com.android.internal.R.styleable.Include_visibility, -1);
-                        final boolean hasWidth = a.hasValue(
-                                com.android.internal.R.styleable.Include_layout_width);
-                        final boolean hasHeight = a.hasValue(
-                                com.android.internal.R.styleable.Include_layout_height);
                         a.recycle();
 
                         // We try to load the layout params set in the <include /> tag. If
@@ -179,19 +175,17 @@
                         // successfully loaded layout params from the <include /> tag,
                         // false means we need to rely on the included layout params.
                         ViewGroup.LayoutParams params = null;
-                        if (hasWidth && hasHeight) {
-                            try {
-                                // ---- START CHANGES
-                                sIsInInclude = true;
-                                // ---- END CHANGES
+                        try {
+                            // ---- START CHANGES
+                            sIsInInclude = true;
+                            // ---- END CHANGES
 
-                                params = group.generateLayoutParams(attrs);
+                            params = group.generateLayoutParams(attrs);
 
-                            } finally {
-                                // ---- START CHANGES
-                                sIsInInclude = false;
-                                // ---- END CHANGES
-                            }
+                        } finally {
+                            // ---- START CHANGES
+                            sIsInInclude = false;
+                            // ---- END CHANGES
                         }
                         if (params == null) {
                             params = group.generateLayoutParams(childAttrs);