Merge "Add permission checks"
diff --git a/api/current.txt b/api/current.txt
index 4fb9e0a..50579a4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13048,6 +13048,8 @@
     method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
     method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);
     method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, android.graphics.Bitmap.Config);
+    method public static android.graphics.Bitmap createBitmap(android.graphics.Picture);
+    method public static android.graphics.Bitmap createBitmap(android.graphics.Picture, int, int, android.graphics.Bitmap.Config);
     method public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap, int, int, boolean);
     method public int describeContents();
     method public void eraseColor(int);
@@ -14105,6 +14107,7 @@
     method public void endRecording();
     method public int getHeight();
     method public int getWidth();
+    method public boolean requiresHardwareAcceleration();
     method public deprecated void writeToStream(java.io.OutputStream);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index 62cc2a3..ad71e7c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -19,6 +19,7 @@
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
     field public static final deprecated java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
+    field public static final java.lang.String BIND_DATA_SERVICE = "android.permission.BIND_DATA_SERVICE";
     field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
     field public static final java.lang.String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
     field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
@@ -1140,6 +1141,15 @@
 
 package android.hardware.display {
 
+  public final class AmbientBrightnessDayStats implements android.os.Parcelable {
+    method public int describeContents();
+    method public float[] getBucketBoundaries();
+    method public java.time.LocalDate getLocalDate();
+    method public float[] getStats();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.hardware.display.AmbientBrightnessDayStats> CREATOR;
+  }
+
   public final class BrightnessChangeEvent implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 9af80e3..92bf24d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -298,6 +298,15 @@
 
 package android.hardware.display {
 
+  public final class AmbientBrightnessDayStats implements android.os.Parcelable {
+    method public int describeContents();
+    method public float[] getBucketBoundaries();
+    method public java.time.LocalDate getLocalDate();
+    method public float[] getStats();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.hardware.display.AmbientBrightnessDayStats> CREATOR;
+  }
+
   public final class BrightnessChangeEvent implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 8101b16..b0019ac 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -41,6 +41,8 @@
     src/external/ResourceHealthManagerPuller.cpp \
     src/external/CpuTimePerUidPuller.cpp \
     src/external/CpuTimePerUidFreqPuller.cpp \
+    src/external/KernelUidCpuActiveTimeReader.cpp \
+    src/external/KernelUidCpuClusterTimeReader.cpp \
     src/external/StatsPullerManagerImpl.cpp \
     src/logd/LogEvent.cpp \
     src/logd/LogListener.cpp \
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index f545bb0..4e41454 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -551,6 +551,12 @@
     return NO_ERROR;
 }
 
+status_t StatsService::cmd_clear_puller_cache(FILE* out) {
+    mStatsPullerManager.ClearPullerCache();
+    fprintf(out, "Puller cached data removed!\n");
+    return NO_ERROR;
+}
+
 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
                                       const vector<String16>& app) {
     VLOG("StatsService::informAllUidData was called");
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index be20893..fd3ed1d 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -197,6 +197,11 @@
      */
     status_t cmd_dump_memory_info(FILE* out);
 
+  /*
+     * Clear all puller cached data
+     */
+  status_t cmd_clear_puller_cache(FILE* out);
+
     /**
      * Update a configuration.
      */
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index cadc535..da14434 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -59,6 +59,11 @@
     return ret;
 }
 
+void StatsPuller::ClearCache() {
+    lock_guard<std::mutex> lock(mLock);
+    mCachedData.clear();
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index 47cc9f0..bc7c45f 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -38,6 +38,8 @@
 
     bool Pull(std::vector<std::shared_ptr<LogEvent>>* data);
 
+    void ClearCache();
+
 protected:
     // The atom tag id this puller pulls
     const int mTagId;
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 00a1475..4826d96 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -50,10 +50,14 @@
         return mPullerManager.Pull(tagId, data);
     }
 
-    virtual void SetTimeBaseSec(const long timeBaseSec) {
+    void SetTimeBaseSec(const long timeBaseSec) {
         mPullerManager.SetTimeBaseSec(timeBaseSec);
     }
 
+    void ClearPullerCache() {
+        mPullerManager.ClearPullerCache();
+    }
+
  private:
     StatsPullerManagerImpl
         & mPullerManager = StatsPullerManagerImpl::GetInstance();
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index d8e8a41..71b0abe 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -199,6 +199,12 @@
     }
 }
 
+void StatsPullerManagerImpl::ClearPullerCache() {
+    for (auto puller : mPullers) {
+        puller.second->ClearCache();
+    }
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.h b/cmds/statsd/src/external/StatsPullerManagerImpl.h
index 7c59f66..fba3ade 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.h
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.h
@@ -49,6 +49,8 @@
 
     void SetTimeBaseSec(long timeBaseSec) {mTimeBaseSec = timeBaseSec;};
 
+    void ClearPullerCache();
+
 private:
     StatsPullerManagerImpl();
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index fdb0ac9..04c44a3 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -425,6 +425,12 @@
  * safely called after {@link #onPause()} and allows and application to safely
  * wait until {@link #onStop()} to save persistent state.</p>
  *
+ * <p class="note">For applications targeting platforms starting with
+ * {@link android.os.Build.VERSION_CODES#P} {@link #onSaveInstanceState(Bundle)}
+ * will always be called after {@link #onStop}, so an application may safely
+ * perform fragment transactions in {@link #onStop} and will be able to save
+ * persistent state later.</p>
+ *
  * <p>For those methods that are not marked as being killable, the activity's
  * process will not be killed by the system starting from the time the method
  * is called and continuing after it returns.  Thus an activity is in the killable
@@ -1577,8 +1583,11 @@
      * call through to the default implementation, otherwise be prepared to save
      * all of the state of each view yourself.
      *
-     * <p>If called, this method will occur before {@link #onStop}.  There are
-     * no guarantees about whether it will occur before or after {@link #onPause}.
+     * <p>If called, this method will occur after {@link #onStop} for applications
+     * targeting platforms starting with {@link android.os.Build.VERSION_CODES#P}.
+     * For applications targeting earlier platform versions this method will occur
+     * before {@link #onStop} and there are no guarantees about whether it will
+     * occur before or after {@link #onPause}.
      *
      * @param outState Bundle in which to place your saved state.
      *
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 29e091b..42825f0 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -488,12 +488,14 @@
             }
         }
 
-        public boolean isPreHoneycomb() {
-            if (activity != null) {
-                return activity.getApplicationInfo().targetSdkVersion
-                        < android.os.Build.VERSION_CODES.HONEYCOMB;
-            }
-            return false;
+        private boolean isPreHoneycomb() {
+            return activity != null && activity.getApplicationInfo().targetSdkVersion
+                    < android.os.Build.VERSION_CODES.HONEYCOMB;
+        }
+
+        private boolean isPreP() {
+            return activity != null && activity.getApplicationInfo().targetSdkVersion
+                    < android.os.Build.VERSION_CODES.P;
         }
 
         public boolean isPersistable() {
@@ -4165,9 +4167,12 @@
      * {@link Activity#onSaveInstanceState(Bundle)} is also executed in the same call.
      */
     private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {
+        // Before P onSaveInstanceState was called before onStop, starting with P it's
+        // called after. Before Honeycomb state was always saved before onPause.
         final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null
                 && !r.isPreHoneycomb();
-        if (shouldSaveState) {
+        final boolean isPreP = r.isPreP();
+        if (shouldSaveState && isPreP) {
             callActivityOnSaveInstanceState(r);
         }
 
@@ -4186,6 +4191,10 @@
         r.setState(ON_STOP);
         EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
                 r.activity.getComponentName().getClassName(), reason);
+
+        if (shouldSaveState && !isPreP) {
+            callActivityOnSaveInstanceState(r);
+        }
     }
 
     private void updateVisibility(ActivityClientRecord r, boolean show) {
diff --git a/core/java/android/hardware/display/AmbientBrightnessDayStats.java b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
index 41be397..00f3c36 100644
--- a/core/java/android/hardware/display/AmbientBrightnessDayStats.java
+++ b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
@@ -17,6 +17,8 @@
 package android.hardware.display;
 
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -28,11 +30,12 @@
 /**
  * AmbientBrightnessDayStats stores and manipulates brightness stats over a single day.
  * {@see DisplayManager.getAmbientBrightnessStats()}
- * TODO: Make this system API
  *
  * @hide
  */
-public class AmbientBrightnessDayStats implements Parcelable {
+@SystemApi
+@TestApi
+public final class AmbientBrightnessDayStats implements Parcelable {
 
     /** The localdate for which brightness stats are being tracked */
     private final LocalDate mLocalDate;
@@ -48,30 +51,30 @@
      */
     public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
             @NonNull float[] bucketBoundaries) {
-        Preconditions.checkNotNull(localDate);
-        Preconditions.checkNotNull(bucketBoundaries);
-        int numBuckets = bucketBoundaries.length;
-        if (numBuckets < 1) {
-            throw new IllegalArgumentException("Bucket boundaries must contain at least 1 value");
-        }
-        mLocalDate = localDate;
-        mBucketBoundaries = bucketBoundaries;
-        mStats = new float[numBuckets];
+        this(localDate, bucketBoundaries, null);
     }
 
     /**
      * @hide
      */
     public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
-            @NonNull float[] bucketBoundaries, @NonNull float[] stats) {
+            @NonNull float[] bucketBoundaries, float[] stats) {
         Preconditions.checkNotNull(localDate);
         Preconditions.checkNotNull(bucketBoundaries);
-        Preconditions.checkNotNull(stats);
+        Preconditions.checkArrayElementsInRange(bucketBoundaries, 0, Float.MAX_VALUE,
+                "bucketBoundaries");
         if (bucketBoundaries.length < 1) {
             throw new IllegalArgumentException("Bucket boundaries must contain at least 1 value");
         }
-        if (bucketBoundaries.length != stats.length) {
-            throw new IllegalArgumentException("Bucket boundaries and stats must be of same size.");
+        checkSorted(bucketBoundaries);
+        if (stats == null) {
+            stats = new float[bucketBoundaries.length];
+        } else {
+            Preconditions.checkArrayElementsInRange(stats, 0, Float.MAX_VALUE, "stats");
+            if (bucketBoundaries.length != stats.length) {
+                throw new IllegalArgumentException(
+                        "Bucket boundaries and stats must be of same size.");
+            }
         }
         mLocalDate = localDate;
         mBucketBoundaries = bucketBoundaries;
@@ -193,4 +196,16 @@
         }
         return low;
     }
+
+    private static void checkSorted(float[] values) {
+        if (values.length <= 1) {
+            return;
+        }
+        float prevValue = values[0];
+        for (int i = 1; i < values.length; i++) {
+            Preconditions.checkState(prevValue < values[i]);
+            prevValue = values[i];
+        }
+        return;
+    }
 }
diff --git a/core/java/android/text/style/DrawableMarginSpan.java b/core/java/android/text/style/DrawableMarginSpan.java
index 3524179..cd199b3 100644
--- a/core/java/android/text/style/DrawableMarginSpan.java
+++ b/core/java/android/text/style/DrawableMarginSpan.java
@@ -16,60 +16,100 @@
 
 package android.text.style;
 
+import android.annotation.NonNull;
+import android.annotation.Px;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
 import android.text.Layout;
 import android.text.Spanned;
 
-public class DrawableMarginSpan
-implements LeadingMarginSpan, LineHeightSpan
-{
-    public DrawableMarginSpan(Drawable b) {
-        mDrawable = b;
+/**
+ * A span which adds a drawable and a padding to the paragraph it's attached to.
+ * <p>
+ * If the height of the drawable is bigger than the height of the line it's attached to then the
+ * line height is increased to fit the drawable. <code>DrawableMarginSpan</code> allows setting a
+ * padding between the drawable and the text. The default value is 0. The span must be set from the
+ * beginning of the text, otherwise either the span won't be rendered or it will be rendered
+ * incorrectly.
+ * <p>
+ * For example, a drawable and a padding of 20px can be added like this:
+ * <pre>{@code SpannableString string = new SpannableString("Text with a drawable.");
+ * string.setSpan(new DrawableMarginSpan(drawable, 20), 0, string.length(),
+ * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/drawablemarginspan.png" />
+ * <figcaption>Text with a drawable and a padding.</figcaption>
+ * <p>
+ *
+ * @see IconMarginSpan for working with a {@link android.graphics.Bitmap} instead of
+ * a {@link Drawable}.
+ */
+public class DrawableMarginSpan implements LeadingMarginSpan, LineHeightSpan {
+    private static final int STANDARD_PAD_WIDTH = 0;
+
+    @NonNull
+    private final Drawable mDrawable;
+    @Px
+    private final int mPad;
+
+    /**
+     * Creates a {@link DrawableMarginSpan} from a {@link Drawable}. The pad width will be 0.
+     *
+     * @param drawable the drawable to be added
+     */
+    public DrawableMarginSpan(@NonNull Drawable drawable) {
+        this(drawable, STANDARD_PAD_WIDTH);
     }
 
-    public DrawableMarginSpan(Drawable b, int pad) {
-        mDrawable = b;
+    /**
+     * Creates a {@link DrawableMarginSpan} from a {@link Drawable} and a padding, in pixels.
+     *
+     * @param drawable the drawable to be added
+     * @param pad      the distance between the drawable and the text
+     */
+    public DrawableMarginSpan(@NonNull Drawable drawable, int pad) {
+        mDrawable = drawable;
         mPad = pad;
     }
 
+    @Override
     public int getLeadingMargin(boolean first) {
         return mDrawable.getIntrinsicWidth() + mPad;
     }
 
-    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
-                                  int top, int baseline, int bottom,
-                                  CharSequence text, int start, int end,
-                                  boolean first, Layout layout) {
+    @Override
+    public void drawLeadingMargin(@NonNull Canvas c, @NonNull Paint p, int x, int dir,
+            int top, int baseline, int bottom,
+            @NonNull CharSequence text, int start, int end,
+            boolean first, @NonNull Layout layout) {
         int st = ((Spanned) text).getSpanStart(this);
-        int ix = (int)x;
-        int itop = (int)layout.getLineTop(layout.getLineForOffset(st));
+        int ix = (int) x;
+        int itop = (int) layout.getLineTop(layout.getLineForOffset(st));
 
         int dw = mDrawable.getIntrinsicWidth();
         int dh = mDrawable.getIntrinsicHeight();
 
         // XXX What to do about Paint?
-        mDrawable.setBounds(ix, itop, ix+dw, itop+dh);
+        mDrawable.setBounds(ix, itop, ix + dw, itop + dh);
         mDrawable.draw(c);
     }
 
-    public void chooseHeight(CharSequence text, int start, int end,
-                             int istartv, int v,
-                             Paint.FontMetricsInt fm) {
+    @Override
+    public void chooseHeight(@NonNull CharSequence text, int start, int end,
+            int istartv, int v,
+            @NonNull Paint.FontMetricsInt fm) {
         if (end == ((Spanned) text).getSpanEnd(this)) {
             int ht = mDrawable.getIntrinsicHeight();
 
             int need = ht - (v + fm.descent - fm.ascent - istartv);
-            if (need > 0)
+            if (need > 0) {
                 fm.descent += need;
+            }
 
             need = ht - (v + fm.bottom - fm.top - istartv);
-            if (need > 0)
+            if (need > 0) {
                 fm.bottom += need;
+            }
         }
     }
-
-    private Drawable mDrawable;
-    private int mPad;
 }
diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java
index 5b8a6dd..1b16f33 100644
--- a/core/java/android/text/style/DynamicDrawableSpan.java
+++ b/core/java/android/text/style/DynamicDrawableSpan.java
@@ -16,6 +16,9 @@
 
 package android.text.style;
 
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -24,32 +27,71 @@
 import java.lang.ref.WeakReference;
 
 /**
+ * Span that replaces the text it's attached to with a {@link Drawable} that can be aligned with
+ * the bottom or with the baseline of the surrounding text.
+ * <p>
+ * For an implementation that constructs the drawable from various sources (<code>Bitmap</code>,
+ * <code>Drawable</code>, resource id or <code>Uri</code>) use {@link ImageSpan}.
+ * <p>
+ * A simple implementation of <code>DynamicDrawableSpan</code> that uses drawables from resources
+ * looks like this:
+ * <pre>
+ * class MyDynamicDrawableSpan extends DynamicDrawableSpan {
  *
+ * private final Context mContext;
+ * private final int mResourceId;
+ *
+ * public MyDynamicDrawableSpan(Context context, @DrawableRes int resourceId) {
+ *     mContext = context;
+ *     mResourceId = resourceId;
+ * }
+ *
+ * {@literal @}Override
+ * public Drawable getDrawable() {
+ *      Drawable drawable = mContext.getDrawable(mResourceId);
+ *      drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
+ *      return drawable;
+ * }
+ * }</pre>
+ * The class can be used like this:
+ * <pre>
+ * SpannableString string = new SpannableString("Text with a drawable span");
+ * string.setSpan(new MyDynamicDrawableSpan(context, R.mipmap.ic_launcher), 12, 20, Spanned
+ * .SPAN_EXCLUSIVE_EXCLUSIVE);</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/dynamicdrawablespan.png" />
+ * <figcaption>Replacing text with a drawable.</figcaption>
  */
 public abstract class DynamicDrawableSpan extends ReplacementSpan {
-    private static final String TAG = "DynamicDrawableSpan";
-    
+
     /**
      * A constant indicating that the bottom of this span should be aligned
      * with the bottom of the surrounding text, i.e., at the same level as the
      * lowest descender in the text.
      */
     public static final int ALIGN_BOTTOM = 0;
-    
+
     /**
      * A constant indicating that the bottom of this span should be aligned
      * with the baseline of the surrounding text.
      */
     public static final int ALIGN_BASELINE = 1;
-    
+
     protected final int mVerticalAlignment;
-    
+
+    private WeakReference<Drawable> mDrawableRef;
+
+    /**
+     * Creates a {@link DynamicDrawableSpan}. The default vertical alignment is
+     * {@link #ALIGN_BOTTOM}
+     */
     public DynamicDrawableSpan() {
         mVerticalAlignment = ALIGN_BOTTOM;
     }
 
     /**
-     * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}.
+     * Creates a {@link DynamicDrawableSpan} based on a vertical alignment.\
+     *
+     * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}
      */
     protected DynamicDrawableSpan(int verticalAlignment) {
         mVerticalAlignment = verticalAlignment;
@@ -64,22 +106,22 @@
     }
 
     /**
-     * Your subclass must implement this method to provide the bitmap   
+     * Your subclass must implement this method to provide the bitmap
      * to be drawn.  The dimensions of the bitmap must be the same
      * from each call to the next.
      */
     public abstract Drawable getDrawable();
 
     @Override
-    public int getSize(Paint paint, CharSequence text,
-                         int start, int end,
-                         Paint.FontMetricsInt fm) {
+    public int getSize(@NonNull Paint paint, CharSequence text,
+            @IntRange(from = 0) int start, @IntRange(from = 0) int end,
+            @Nullable Paint.FontMetricsInt fm) {
         Drawable d = getCachedDrawable();
         Rect rect = d.getBounds();
 
         if (fm != null) {
-            fm.ascent = -rect.bottom; 
-            fm.descent = 0; 
+            fm.ascent = -rect.bottom;
+            fm.descent = 0;
 
             fm.top = fm.ascent;
             fm.bottom = 0;
@@ -89,12 +131,12 @@
     }
 
     @Override
-    public void draw(Canvas canvas, CharSequence text,
-                     int start, int end, float x, 
-                     int top, int y, int bottom, Paint paint) {
+    public void draw(@NonNull Canvas canvas, CharSequence text,
+            @IntRange(from = 0) int start, @IntRange(from = 0) int end, float x,
+            int top, int y, int bottom, @NonNull Paint paint) {
         Drawable b = getCachedDrawable();
         canvas.save();
-        
+
         int transY = bottom - b.getBounds().bottom;
         if (mVerticalAlignment == ALIGN_BASELINE) {
             transY -= paint.getFontMetricsInt().descent;
@@ -109,8 +151,9 @@
         WeakReference<Drawable> wr = mDrawableRef;
         Drawable d = null;
 
-        if (wr != null)
+        if (wr != null) {
             d = wr.get();
+        }
 
         if (d == null) {
             d = getDrawable();
@@ -119,7 +162,5 @@
 
         return d;
     }
-
-    private WeakReference<Drawable> mDrawableRef;
 }
 
diff --git a/core/java/android/text/style/IconMarginSpan.java b/core/java/android/text/style/IconMarginSpan.java
index 304c83f..ad78bd5 100644
--- a/core/java/android/text/style/IconMarginSpan.java
+++ b/core/java/android/text/style/IconMarginSpan.java
@@ -16,57 +16,98 @@
 
 package android.text.style;
 
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Px;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.text.Layout;
 import android.text.Spanned;
 
-public class IconMarginSpan
-implements LeadingMarginSpan, LineHeightSpan
-{
-    public IconMarginSpan(Bitmap b) {
-        mBitmap = b;
+/**
+ * Paragraph affecting span, that draws a bitmap at the beginning of a text. The span also allows
+ * setting a padding between the bitmap and the text. The default value of the padding is 0px. The
+ * span should be attached from the first character of the text.
+ * <p>
+ * For example, an <code>IconMarginSpan</code> with a bitmap and a padding of 30px can be set
+ * like this:
+ * <pre>
+ * SpannableString string = new SpannableString("Text with icon and padding");
+ * string.setSpan(new IconMarginSpan(bitmap, 30), 0, string.length(),
+ * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * </pre>
+ * <img src="{@docRoot}reference/android/images/text/style/iconmarginspan.png" />
+ * <figcaption>Text with <code>IconMarginSpan</code></figcaption>
+ * <p>
+ *
+ * @see DrawableMarginSpan for working with a {@link android.graphics.drawable.Drawable} instead of
+ * a {@link Bitmap}.
+ */
+public class IconMarginSpan implements LeadingMarginSpan, LineHeightSpan {
+
+    @NonNull
+    private final Bitmap mBitmap;
+    @Px
+    private final int mPad;
+
+    /**
+     * Creates an {@link IconMarginSpan} from a {@link Bitmap}.
+     *
+     * @param bitmap bitmap to be rendered at the beginning of the text
+     */
+    public IconMarginSpan(@NonNull Bitmap bitmap) {
+        this(bitmap, 0);
     }
 
-    public IconMarginSpan(Bitmap b, int pad) {
-        mBitmap = b;
+    /**
+     * Creates an {@link IconMarginSpan} from a {@link Bitmap}.
+     *
+     * @param bitmap bitmap to be rendered at the beginning of the text
+     * @param pad    padding width, in pixels, between the bitmap and the text
+     */
+    public IconMarginSpan(@NonNull Bitmap bitmap, @IntRange(from = 0) int pad) {
+        mBitmap = bitmap;
         mPad = pad;
     }
 
+    @Override
     public int getLeadingMargin(boolean first) {
         return mBitmap.getWidth() + mPad;
     }
 
+    @Override
     public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
-                                  int top, int baseline, int bottom,
-                                  CharSequence text, int start, int end,
-                                  boolean first, Layout layout) {
+            int top, int baseline, int bottom,
+            CharSequence text, int start, int end,
+            boolean first, Layout layout) {
         int st = ((Spanned) text).getSpanStart(this);
         int itop = layout.getLineTop(layout.getLineForOffset(st));
 
-        if (dir < 0)
+        if (dir < 0) {
             x -= mBitmap.getWidth();
+        }
 
         c.drawBitmap(mBitmap, x, itop, p);
     }
 
+    @Override
     public void chooseHeight(CharSequence text, int start, int end,
-                             int istartv, int v,
-                             Paint.FontMetricsInt fm) {
+            int istartv, int v,
+            Paint.FontMetricsInt fm) {
         if (end == ((Spanned) text).getSpanEnd(this)) {
             int ht = mBitmap.getHeight();
 
             int need = ht - (v + fm.descent - fm.ascent - istartv);
-            if (need > 0)
+            if (need > 0) {
                 fm.descent += need;
+            }
 
             need = ht - (v + fm.bottom - fm.top - istartv);
-            if (need > 0)
+            if (need > 0) {
                 fm.bottom += need;
+            }
         }
     }
 
-    private Bitmap mBitmap;
-    private int mPad;
 }
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index b0bff68..95f0b43 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -17,6 +17,8 @@
 package android.text.style;
 
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -27,18 +29,49 @@
 
 import java.io.InputStream;
 
+/**
+ * Span that replaces the text it's attached to with a {@link Drawable} that can be aligned with
+ * the bottom or with the baseline of the surrounding text. The drawable can be constructed from
+ * varied sources:
+ * <ul>
+ * <li>{@link Bitmap} - see {@link #ImageSpan(Context, Bitmap)} and
+ * {@link #ImageSpan(Context, Bitmap, int)}
+ * </li>
+ * <li>{@link Drawable} - see {@link #ImageSpan(Drawable, int)}</li>
+ * <li>resource id - see {@link #ImageSpan(Context, int, int)}</li>
+ * <li>{@link Uri} - see {@link #ImageSpan(Context, Uri, int)}</li>
+ * </ul>
+ * The default value for the vertical alignment is {@link DynamicDrawableSpan#ALIGN_BOTTOM}
+ * <p>
+ * For example, an <code>ImagedSpan</code> can be used like this:
+ * <pre>
+ * SpannableString string = SpannableString("Bottom: span.\nBaseline: span.");
+ * // using the default alignment: ALIGN_BOTTOM
+ * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher), 7, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher, DynamicDrawableSpan.ALIGN_BASELINE),
+ * 22, 23, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * </pre>
+ * <img src="{@docRoot}reference/android/images/text/style/imagespan.png" />
+ * <figcaption>Text with <code>ImageSpan</code>s aligned bottom and baseline.</figcaption>
+ */
 public class ImageSpan extends DynamicDrawableSpan {
+
+    @Nullable
     private Drawable mDrawable;
+    @Nullable
     private Uri mContentUri;
+    @DrawableRes
     private int mResourceId;
+    @Nullable
     private Context mContext;
+    @Nullable
     private String mSource;
 
     /**
      * @deprecated Use {@link #ImageSpan(Context, Bitmap)} instead.
      */
     @Deprecated
-    public ImageSpan(Bitmap b) {
+    public ImageSpan(@NonNull Bitmap b) {
         this(null, b, ALIGN_BOTTOM);
     }
 
@@ -46,80 +79,143 @@
      * @deprecated Use {@link #ImageSpan(Context, Bitmap, int)} instead.
      */
     @Deprecated
-    public ImageSpan(Bitmap b, int verticalAlignment) {
+    public ImageSpan(@NonNull Bitmap b, int verticalAlignment) {
         this(null, b, verticalAlignment);
     }
 
-    public ImageSpan(Context context, Bitmap b) {
-        this(context, b, ALIGN_BOTTOM);
+    /**
+     * Constructs an {@link ImageSpan} from a {@link Context} and a {@link Bitmap} with the default
+     * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}
+     *
+     * @param context context used to create a drawable from {@param bitmap} based on the display
+     *                metrics of the resources
+     * @param bitmap  bitmap to be rendered
+     */
+    public ImageSpan(@NonNull Context context, @NonNull Bitmap bitmap) {
+        this(context, bitmap, ALIGN_BOTTOM);
     }
 
     /**
+     * Constructs an {@link ImageSpan} from a {@link Context}, a {@link Bitmap} and a vertical
+     * alignment.
+     *
+     * @param context           context used to create a drawable from {@param bitmap} based on
+     *                          the display metrics of the resources
+     * @param bitmap            bitmap to be rendered
      * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
-     * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
+     *                          {@link DynamicDrawableSpan#ALIGN_BASELINE}
      */
-    public ImageSpan(Context context, Bitmap b, int verticalAlignment) {
+    public ImageSpan(@NonNull Context context, @NonNull Bitmap bitmap, int verticalAlignment) {
         super(verticalAlignment);
         mContext = context;
         mDrawable = context != null
-                ? new BitmapDrawable(context.getResources(), b)
-                : new BitmapDrawable(b);
+                ? new BitmapDrawable(context.getResources(), bitmap)
+                : new BitmapDrawable(bitmap);
         int width = mDrawable.getIntrinsicWidth();
         int height = mDrawable.getIntrinsicHeight();
-        mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); 
-    }
-
-    public ImageSpan(Drawable d) {
-        this(d, ALIGN_BOTTOM);
+        mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0);
     }
 
     /**
-     * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
-     * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
+     * Constructs an {@link ImageSpan} from a drawable with the default
+     * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}.
+     *
+     * @param drawable drawable to be rendered
      */
-    public ImageSpan(Drawable d, int verticalAlignment) {
-        super(verticalAlignment);
-        mDrawable = d;
-    }
-
-    public ImageSpan(Drawable d, String source) {
-        this(d, source, ALIGN_BOTTOM);
+    public ImageSpan(@NonNull Drawable drawable) {
+        this(drawable, ALIGN_BOTTOM);
     }
 
     /**
+     * Constructs an {@link ImageSpan} from a drawable and a vertical alignment.
+     *
+     * @param drawable          drawable to be rendered
      * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
-     * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
+     *                          {@link DynamicDrawableSpan#ALIGN_BASELINE}
      */
-    public ImageSpan(Drawable d, String source, int verticalAlignment) {
+    public ImageSpan(@NonNull Drawable drawable, int verticalAlignment) {
         super(verticalAlignment);
-        mDrawable = d;
+        mDrawable = drawable;
+    }
+
+    /**
+     * Constructs an {@link ImageSpan} from a drawable and a source with the default
+     * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}
+     *
+     * @param drawable drawable to be rendered
+     * @param source   drawable's Uri source
+     */
+    public ImageSpan(@NonNull Drawable drawable, @NonNull String source) {
+        this(drawable, source, ALIGN_BOTTOM);
+    }
+
+    /**
+     * Constructs an {@link ImageSpan} from a drawable, a source and a vertical alignment.
+     *
+     * @param drawable          drawable to be rendered
+     * @param source            drawable's uri source
+     * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
+     *                          {@link DynamicDrawableSpan#ALIGN_BASELINE}
+     */
+    public ImageSpan(@NonNull Drawable drawable, @NonNull String source, int verticalAlignment) {
+        super(verticalAlignment);
+        mDrawable = drawable;
         mSource = source;
     }
 
-    public ImageSpan(Context context, Uri uri) {
+    /**
+     * Constructs an {@link ImageSpan} from a {@link Context} and a {@link Uri} with the default
+     * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}. The Uri source can be retrieved via
+     * {@link #getSource()}
+     *
+     * @param context context used to create a drawable from {@param bitmap} based on the display
+     *                metrics of the resources
+     * @param uri     {@link Uri} used to construct the drawable that will be rendered
+     */
+    public ImageSpan(@NonNull Context context, @NonNull Uri uri) {
         this(context, uri, ALIGN_BOTTOM);
     }
 
     /**
+     * Constructs an {@link ImageSpan} from a {@link Context}, a {@link Uri} and a vertical
+     * alignment. The Uri source can be retrieved via {@link #getSource()}
+     *
+     * @param context           context used to create a drawable from {@param bitmap} based on
+     *                          the display
+     *                          metrics of the resources
+     * @param uri               {@link Uri} used to construct the drawable that will be rendered.
      * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
-     * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
+     *                          {@link DynamicDrawableSpan#ALIGN_BASELINE}
      */
-    public ImageSpan(Context context, Uri uri, int verticalAlignment) {
+    public ImageSpan(@NonNull Context context, @NonNull Uri uri, int verticalAlignment) {
         super(verticalAlignment);
         mContext = context;
         mContentUri = uri;
         mSource = uri.toString();
     }
 
-    public ImageSpan(Context context, @DrawableRes int resourceId) {
+    /**
+     * Constructs an {@link ImageSpan} from a {@link Context} and a resource id with the default
+     * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}
+     *
+     * @param context    context used to retrieve the drawable from resources
+     * @param resourceId drawable resource id based on which the drawable is retrieved
+     */
+    public ImageSpan(@NonNull Context context, @DrawableRes int resourceId) {
         this(context, resourceId, ALIGN_BOTTOM);
     }
 
     /**
+     * Constructs an {@link ImageSpan} from a {@link Context}, a resource id and a vertical
+     * alignment.
+     *
+     * @param context           context used to retrieve the drawable from resources
+     * @param resourceId        drawable resource id based on which the drawable is retrieved.
      * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
-     * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
+     *                          {@link DynamicDrawableSpan#ALIGN_BASELINE}
      */
-    public ImageSpan(Context context, @DrawableRes int resourceId, int verticalAlignment) {
+    public ImageSpan(@NonNull Context context, @DrawableRes int resourceId,
+            int verticalAlignment) {
         super(verticalAlignment);
         mContext = context;
         mResourceId = resourceId;
@@ -128,10 +224,10 @@
     @Override
     public Drawable getDrawable() {
         Drawable drawable = null;
-        
+
         if (mDrawable != null) {
             drawable = mDrawable;
-        } else  if (mContentUri != null) {
+        } else if (mContentUri != null) {
             Bitmap bitmap = null;
             try {
                 InputStream is = mContext.getContentResolver().openInputStream(
@@ -142,7 +238,7 @@
                         drawable.getIntrinsicHeight());
                 is.close();
             } catch (Exception e) {
-                Log.e("sms", "Failed to loaded content " + mContentUri, e);
+                Log.e("ImageSpan", "Failed to loaded content " + mContentUri, e);
             }
         } else {
             try {
@@ -150,8 +246,8 @@
                 drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
                         drawable.getIntrinsicHeight());
             } catch (Exception e) {
-                Log.e("sms", "Unable to find resource: " + mResourceId);
-            }                
+                Log.e("ImageSpan", "Unable to find resource: " + mResourceId);
+            }
         }
 
         return drawable;
@@ -159,9 +255,12 @@
 
     /**
      * Returns the source string that was saved during construction.
+     *
+     * @return the source string that was saved during construction
+     * @see #ImageSpan(Drawable, String) and this{@link #ImageSpan(Context, Uri)}
      */
+    @Nullable
     public String getSource() {
         return mSource;
     }
-
 }
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
index 1ebee82..50ee5f3 100644
--- a/core/java/android/text/style/LineHeightSpan.java
+++ b/core/java/android/text/style/LineHeightSpan.java
@@ -19,16 +19,42 @@
 import android.graphics.Paint;
 import android.text.TextPaint;
 
-public interface LineHeightSpan
-extends ParagraphStyle, WrapTogetherSpan
-{
+/**
+ * The classes that affect the height of the line should implement this interface.
+ */
+public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan {
+    /**
+     * Classes that implement this should define how the height is being calculated.
+     *
+     * @param text       the text
+     * @param start      the start of the line
+     * @param end        the end of the line
+     * @param spanstartv the start of the span
+     * @param lineHeight the line height
+     * @param fm         font metrics of the paint, in integers
+     */
     public void chooseHeight(CharSequence text, int start, int end,
-                             int spanstartv, int v,
-                             Paint.FontMetricsInt fm);
+            int spanstartv, int lineHeight,
+            Paint.FontMetricsInt fm);
 
+    /**
+     * The classes that affect the height of the line with respect to density, should implement this
+     * interface.
+     */
     public interface WithDensity extends LineHeightSpan {
+
+        /**
+         * Classes that implement this should define how the height is being calculated.
+         *
+         * @param text       the text
+         * @param start      the start of the line
+         * @param end        the end of the line
+         * @param spanstartv the start of the span
+         * @param lineHeight the line height
+         * @param paint      the paint
+         */
         public void chooseHeight(CharSequence text, int start, int end,
-                                 int spanstartv, int v,
-                                 Paint.FontMetricsInt fm, TextPaint paint);
+                int spanstartv, int lineHeight,
+                Paint.FontMetricsInt fm, TextPaint paint);
     }
 }
diff --git a/core/java/android/text/style/MaskFilterSpan.java b/core/java/android/text/style/MaskFilterSpan.java
index 2ff52a8..d76ef94 100644
--- a/core/java/android/text/style/MaskFilterSpan.java
+++ b/core/java/android/text/style/MaskFilterSpan.java
@@ -18,15 +18,36 @@
 
 import android.graphics.MaskFilter;
 import android.text.TextPaint;
-
+/**
+ * Span that allows setting a {@link MaskFilter} to the text it's attached to.
+ * <p>
+ * For example, to blur a text, a {@link android.graphics.BlurMaskFilter} can be used:
+ * <pre>
+ * MaskFilter blurMask = new BlurMaskFilter(5f, BlurMaskFilter.Blur.NORMAL);
+ * SpannableString string = new SpannableString("Text with blur mask");
+ * string.setSpan(new MaskFilterSpan(blurMask), 10, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * </pre>
+ * <img src="{@docRoot}reference/android/images/text/style/maskfilterspan.png" />
+ * <figcaption>Text blurred with the <code>MaskFilterSpan</code>.</figcaption>
+ */
 public class MaskFilterSpan extends CharacterStyle implements UpdateAppearance {
 
     private MaskFilter mFilter;
 
+    /**
+     * Creates a {@link MaskFilterSpan} from a {@link MaskFilter}.
+     *
+     * @param filter the filter to be applied to the <code>TextPaint</code>
+     */
     public MaskFilterSpan(MaskFilter filter) {
         mFilter = filter;
     }
 
+    /**
+     * Return the mask filter for this span.
+     *
+     * @return the mask filter for this span
+     */
     public MaskFilter getMaskFilter() {
         return mFilter;
     }
diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java
index f900db5..bdfa700 100644
--- a/core/java/android/text/style/StyleSpan.java
+++ b/core/java/android/text/style/StyleSpan.java
@@ -16,6 +16,7 @@
 
 package android.text.style;
 
+import android.annotation.NonNull;
 import android.graphics.Paint;
 import android.graphics.Typeface;
 import android.os.Parcel;
@@ -24,55 +25,76 @@
 import android.text.TextUtils;
 
 /**
- * 
- * Describes a style in a span.
+ * Span that allows setting the style of the text it's attached to.
+ * Possible styles are: {@link Typeface#NORMAL}, {@link Typeface#BOLD}, {@link Typeface#ITALIC} and
+ * {@link Typeface#BOLD_ITALIC}.
+ * <p>
  * Note that styles are cumulative -- if both bold and italic are set in
  * separate spans, or if the base style is bold and a span calls for italic,
  * you get bold italic.  You can't turn off a style from the base style.
- *
+ * <p>
+ * For example, the <code>StyleSpan</code> can be used like this:
+ * <pre>
+ * SpannableString string = new SpannableString("Bold and italic text");
+ * string.setSpan(new StyleSpan(Typeface.BOLD), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * string.setSpan(new StyleSpan(Typeface.ITALIC), 9, 15, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * </pre>
+ * <img src="{@docRoot}reference/android/images/text/style/stylespan.png" />
+ * <figcaption>Text styled bold and italic with the <code>StyleSpan</code>.</figcaption>
  */
 public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
 
     private final int mStyle;
 
     /**
-     * 
+     * Creates a {@link StyleSpan} from a style.
+     *
      * @param style An integer constant describing the style for this span. Examples
-     * include bold, italic, and normal. Values are constants defined 
-     * in {@link android.graphics.Typeface}.
+     *              include bold, italic, and normal. Values are constants defined
+     *              in {@link Typeface}.
      */
     public StyleSpan(int style) {
         mStyle = style;
     }
 
-    public StyleSpan(Parcel src) {
+    /**
+     * Creates a {@link StyleSpan} from a parcel.
+     *
+     * @param src the parcel
+     */
+    public StyleSpan(@NonNull Parcel src) {
         mStyle = src.readInt();
     }
-    
+
+    @Override
     public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
 
     /** @hide */
+    @Override
     public int getSpanTypeIdInternal() {
         return TextUtils.STYLE_SPAN;
     }
-    
+
+    @Override
     public int describeContents() {
         return 0;
     }
 
+    @Override
     public void writeToParcel(Parcel dest, int flags) {
         writeToParcelInternal(dest, flags);
     }
 
     /** @hide */
-    public void writeToParcelInternal(Parcel dest, int flags) {
+    @Override
+    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
         dest.writeInt(mStyle);
     }
 
     /**
-     * Returns the style constant defined in {@link android.graphics.Typeface}. 
+     * Returns the style constant defined in {@link Typeface}.
      */
     public int getStyle() {
         return mStyle;
diff --git a/core/java/android/text/style/TabStopSpan.java b/core/java/android/text/style/TabStopSpan.java
index 0566428..2cceb2c 100644
--- a/core/java/android/text/style/TabStopSpan.java
+++ b/core/java/android/text/style/TabStopSpan.java
@@ -16,39 +16,54 @@
 
 package android.text.style;
 
+import android.annotation.IntRange;
+import android.annotation.Px;
+
 /**
- * Represents a single tab stop on a line.
+ * Paragraph affecting span that changes the position of the tab with respect to
+ * the leading margin of the line. <code>TabStopSpan</code> will only affect the first tab
+ * encountered on the first line of the text.
  */
-public interface TabStopSpan
-extends ParagraphStyle
-{
-    /**
-     * Returns the offset of the tab stop from the leading margin of the
-     * line.
-     * @return the offset
-     */
-    public int getTabStop();
+public interface TabStopSpan extends ParagraphStyle {
 
     /**
-     * The default implementation of TabStopSpan.
+     * Returns the offset of the tab stop from the leading margin of the line, in pixels.
+     *
+     * @return the offset, in pixels
      */
-    public static class Standard
-    implements TabStopSpan
-    {
+    int getTabStop();
+
+    /**
+     * The default implementation of TabStopSpan that allows setting the offset of the tab stop
+     * from the leading margin of the first line of text.
+     * <p>
+     * Let's consider that we have the following text: <i>"\tParagraph text beginning with tab."</i>
+     * and we want to move the tab stop with 100px. This can be achieved like this:
+     * <pre>
+     * SpannableString string = new SpannableString("\tParagraph text beginning with tab.");
+     * string.setSpan(new TabStopSpan.Standard(100), 0, string.length(),
+     * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);</pre>
+     * <img src="{@docRoot}reference/android/images/text/style/tabstopspan.png" />
+     * <figcaption>Text with a tab stop and a <code>TabStopSpan</code></figcaption>
+     */
+    class Standard implements TabStopSpan {
+
+        @Px
+        private int mTabOffset;
+
         /**
-         * Constructor.
+         * Constructs a {@link TabStopSpan.Standard} based on an offset.
          *
-         * @param where the offset of the tab stop from the leading margin of
-         *        the line
+         * @param offset the offset of the tab stop from the leading margin of
+         *               the line, in pixels
          */
-        public Standard(int where) {
-            mTab = where;
+        public Standard(@IntRange(from = 0) int offset) {
+            mTabOffset = offset;
         }
 
+        @Override
         public int getTabStop() {
-            return mTab;
+            return mTabOffset;
         }
-
-        private int mTab;
     }
 }
diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java
index aa622d8..1622812 100644
--- a/core/java/android/text/style/TypefaceSpan.java
+++ b/core/java/android/text/style/TypefaceSpan.java
@@ -16,6 +16,7 @@
 
 package android.text.style;
 
+import android.annotation.NonNull;
 import android.graphics.Paint;
 import android.graphics.Typeface;
 import android.os.Parcel;
@@ -24,42 +25,59 @@
 import android.text.TextUtils;
 
 /**
- * Changes the typeface family of the text to which the span is attached.
+ * Changes the typeface family of the text to which the span is attached. Examples of typeface
+ * family include "monospace", "serif", and "sans-serif".
+ * <p>
+ * For example, change the typeface of a text to "monospace" like this:
+ * <pre>
+ * SpannableString string = new SpannableString("Text with typeface span");
+ * string.setSpan(new TypefaceSpan("monospace"), 10, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * </pre>
+ * <img src="{@docRoot}reference/android/images/text/style/typefacespan.png" />
+ * <figcaption>Text with "monospace" typeface family.</figcaption>
  */
 public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {
+
     private final String mFamily;
 
     /**
-     * @param family The font family for this typeface.  Examples include
-     * "monospace", "serif", and "sans-serif".
+     * Constructs a {@link TypefaceSpan} based on a font family.
+     *
+     * @param family The font family for this typeface. Examples include
+     *               "monospace", "serif", and "sans-serif".
      */
     public TypefaceSpan(String family) {
         mFamily = family;
     }
 
-    public TypefaceSpan(Parcel src) {
+    public TypefaceSpan(@NonNull Parcel src) {
         mFamily = src.readString();
     }
-    
+
+    @Override
     public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
 
     /** @hide */
+    @Override
     public int getSpanTypeIdInternal() {
         return TextUtils.TYPEFACE_SPAN;
     }
-    
+
+    @Override
     public int describeContents() {
         return 0;
     }
 
-    public void writeToParcel(Parcel dest, int flags) {
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         writeToParcelInternal(dest, flags);
     }
 
     /** @hide */
-    public void writeToParcelInternal(Parcel dest, int flags) {
+    @Override
+    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
         dest.writeString(mFamily);
     }
 
@@ -71,16 +89,16 @@
     }
 
     @Override
-    public void updateDrawState(TextPaint ds) {
-        apply(ds, mFamily);
+    public void updateDrawState(@NonNull TextPaint textPaint) {
+        apply(textPaint, mFamily);
     }
 
     @Override
-    public void updateMeasureState(TextPaint paint) {
-        apply(paint, mFamily);
+    public void updateMeasureState(@NonNull TextPaint textPaint) {
+        apply(textPaint, mFamily);
     }
 
-    private static void apply(Paint paint, String family) {
+    private static void apply(@NonNull Paint paint, String family) {
         int oldStyle;
 
         Typeface old = paint.getTypeface();
diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java
index 58239ef..eab1ef4 100644
--- a/core/java/android/text/style/URLSpan.java
+++ b/core/java/android/text/style/URLSpan.java
@@ -16,6 +16,7 @@
 
 package android.text.style;
 
+import android.annotation.NonNull;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
@@ -27,40 +28,71 @@
 import android.util.Log;
 import android.view.View;
 
+/**
+ * Implementation of the {@link ClickableSpan} that allows setting a url string. When
+ * selecting and clicking on the text to which the span is attached, the <code>URLSpan</code>
+ * will try to open the url, by launching an an Activity with an {@link Intent#ACTION_VIEW} intent.
+ * <p>
+ * For example, a <code>URLSpan</code> can be used like this:
+ * <pre>
+ * SpannableString string = new SpannableString("Text with a url span");
+ * string.setSpan(new URLSpan("http://www.developer.android.com"), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * </pre>
+ * <img src="{@docRoot}reference/android/images/text/style/urlspan.png" />
+ * <figcaption>Text with <code>URLSpan</code>.</figcaption>
+ */
 public class URLSpan extends ClickableSpan implements ParcelableSpan {
 
     private final String mURL;
 
+    /**
+     * Constructs a {@link URLSpan} from a url string.
+     *
+     * @param url the url string
+     */
     public URLSpan(String url) {
         mURL = url;
     }
 
-    public URLSpan(Parcel src) {
+    /**
+     * Constructs a {@link URLSpan} from a parcel.
+     */
+    public URLSpan(@NonNull Parcel src) {
         mURL = src.readString();
     }
-    
+
+    @Override
     public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
 
     /** @hide */
+    @Override
     public int getSpanTypeIdInternal() {
         return TextUtils.URL_SPAN;
     }
-    
+
+    @Override
     public int describeContents() {
         return 0;
     }
 
-    public void writeToParcel(Parcel dest, int flags) {
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         writeToParcelInternal(dest, flags);
     }
 
     /** @hide */
-    public void writeToParcelInternal(Parcel dest, int flags) {
+    @Override
+    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
         dest.writeString(mURL);
     }
 
+    /**
+     * Get the url string for this span.
+     *
+     * @return the url string.
+     */
     public String getURL() {
         return mURL;
     }
diff --git a/core/java/android/widget/MediaControlView2.java b/core/java/android/widget/MediaControlView2.java
index 2e4cccf..5f6d9ce 100644
--- a/core/java/android/widget/MediaControlView2.java
+++ b/core/java/android/widget/MediaControlView2.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemApi;
 import android.content.Context;
 import android.media.session.MediaController;
 import android.media.update.ApiLoader;
@@ -163,14 +162,6 @@
     }
 
     /**
-     * @hide
-     */
-    @SystemApi
-    public MediaControlView2Provider getProvider() {
-        return mProvider;
-    }
-
-    /**
      * Sets MediaController instance to control corresponding MediaSession.
      */
     public void setController(MediaController controller) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index f9a2341..e69a360 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -55,6 +55,8 @@
     public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10;
     /** Do not enfore hidden API access restrictions. */
     public static final int DISABLE_HIDDEN_API_CHECKS = 1 << 11;
+    /** Force generation of native debugging information for backtraces. */
+    public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12;
 
     /** No external storage should be mounted. */
     public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 43d5b23..d58b95a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1785,13 +1785,22 @@
 
     <!-- Must be required by an ImsService to ensure that only the
          system can bind to it.
-         <p>Protection level: signature|privileged
+         <p>Protection level: signature|privileged|vendorPrivileged
          @SystemApi
          @hide
     -->
     <permission android:name="android.permission.BIND_IMS_SERVICE"
         android:protectionLevel="signature|privileged|vendorPrivileged" />
 
+    <!-- Must be required by a DataService to ensure that only the
+         system can bind to it.
+         <p>Protection level: signature|privileged|vendorPrivileged
+         @SystemApi
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_DATA_SERVICE"
+        android:protectionLevel="signature|privileged|vendorPrivileged" />
+
     <!-- Allows an application to manage embedded subscriptions (those on a eUICC) through
          EuiccManager APIs.
          <p>Protection level: signature|privileged|development
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 224503b..a240616 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4815,7 +4815,7 @@
     A toast message shown when an app shortcut that was restored from a previous device is clicked,
     but it cannot be started because the shortcut was created by a newer version of the app.
     -->
-    <string name="shortcut_restored_on_lower_version">This shortcut requires latest app</string>
+    <string name="shortcut_restored_on_lower_version">App version downgraded, or isn\u2019t compatible with this shortcut</string>
 
     <!--
     A toast message shown when an app shortcut that was restored from a previous device is clicked,
diff --git a/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java b/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java
index 84409d4..f90ae34 100644
--- a/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java
+++ b/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java
@@ -16,8 +16,11 @@
 
 package android.hardware.display;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -27,20 +30,53 @@
 import org.junit.runner.RunWith;
 
 import java.time.LocalDate;
+import java.util.Arrays;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class AmbientBrightnessDayStatsTest {
 
+    private static final LocalDate LOCAL_DATE = LocalDate.now();
+    private static final float[] BUCKET_BOUNDARIES = {0, 1, 10, 100};
+    private static final float[] STATS = {1.3f, 2.6f, 5.8f, 10};
+
+    @Test
+    public void testParamsMustNotBeNull() {
+        assertThrows(NullPointerException.class,
+                () -> new AmbientBrightnessDayStats(null, BUCKET_BOUNDARIES));
+
+        assertThrows(NullPointerException.class,
+                () -> new AmbientBrightnessDayStats(LOCAL_DATE, null));
+
+        assertThrows(NullPointerException.class,
+                () -> new AmbientBrightnessDayStats(null, BUCKET_BOUNDARIES, STATS));
+
+        assertThrows(NullPointerException.class,
+                () -> new AmbientBrightnessDayStats(LOCAL_DATE, null, STATS));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testBucketBoundariesMustNotBeEmpty() {
+        new AmbientBrightnessDayStats(LocalDate.now(), new float[]{});
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testStatsAndBoundariesMustHaveSameLength() {
+        float[] stats = Arrays.copyOf(STATS, STATS.length + 1);
+        stats[stats.length - 1] = 0;
+        new AmbientBrightnessDayStats(LOCAL_DATE, BUCKET_BOUNDARIES, stats);
+    }
+
     @Test
     public void testAmbientBrightnessDayStatsAdd() {
-        AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LocalDate.now(),
-                new float[]{0, 1, 10, 100});
+        AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
+                BUCKET_BOUNDARIES);
         dayStats.log(0, 1);
         dayStats.log(0.5f, 1.5f);
         dayStats.log(50, 12.5f);
         dayStats.log(2000, 1.24f);
         dayStats.log(-10, 0.5f);
+        assertEquals(4, dayStats.getStats().length);
         assertEquals(2.5f, dayStats.getStats()[0], 0);
         assertEquals(0, dayStats.getStats()[1], 0);
         assertEquals(12.5f, dayStats.getStats()[2], 0);
@@ -48,38 +84,12 @@
     }
 
     @Test
-    public void testAmbientBrightnessDayStatsEquals() {
-        LocalDate today = LocalDate.now();
-        AmbientBrightnessDayStats dayStats1 = new AmbientBrightnessDayStats(today,
-                new float[]{0, 1, 10, 100});
-        AmbientBrightnessDayStats dayStats2 = new AmbientBrightnessDayStats(today,
-                new float[]{0, 1, 10, 100}, new float[4]);
-        AmbientBrightnessDayStats dayStats3 = new AmbientBrightnessDayStats(today,
-                new float[]{0, 1, 10, 100}, new float[]{1, 3, 5, 7});
-        AmbientBrightnessDayStats dayStats4 = new AmbientBrightnessDayStats(today,
-                new float[]{0, 1, 10, 100}, new float[]{1, 3, 5, 0});
-        assertEquals(dayStats1, dayStats2);
-        assertEquals(dayStats1.hashCode(), dayStats2.hashCode());
-        assertNotEquals(dayStats1, dayStats3);
-        assertNotEquals(dayStats1.hashCode(), dayStats3.hashCode());
-        dayStats4.log(100, 7);
-        assertEquals(dayStats3, dayStats4);
-        assertEquals(dayStats3.hashCode(), dayStats4.hashCode());
-    }
-
-    @Test
-    public void testAmbientBrightnessDayStatsIncorrectInit() {
-        try {
-            new AmbientBrightnessDayStats(LocalDate.now(), new float[]{1, 10, 100},
-                    new float[]{1, 5, 6, 7});
-        } catch (IllegalArgumentException e) {
-            // Expected
-        }
-        try {
-            new AmbientBrightnessDayStats(LocalDate.now(), new float[]{});
-        } catch (IllegalArgumentException e) {
-            // Expected
-        }
+    public void testGetters() {
+        AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
+                BUCKET_BOUNDARIES, STATS);
+        assertEquals(LOCAL_DATE, dayStats.getLocalDate());
+        assertArrayEquals(BUCKET_BOUNDARIES, dayStats.getBucketBoundaries(), 0);
+        assertArrayEquals(STATS, dayStats.getStats(), 0);
     }
 
     @Test
@@ -100,4 +110,62 @@
                 parcel);
         assertEquals(stats, statsAgain);
     }
+
+    @Test
+    public void testAmbientBrightnessDayStatsEquals() {
+        AmbientBrightnessDayStats emptyDayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
+                BUCKET_BOUNDARIES);
+        AmbientBrightnessDayStats identicalEmptyDayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
+                BUCKET_BOUNDARIES, new float[BUCKET_BOUNDARIES.length]);
+        assertEquals(emptyDayStats, identicalEmptyDayStats);
+        assertEquals(emptyDayStats.hashCode(), identicalEmptyDayStats.hashCode());
+
+        AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
+                BUCKET_BOUNDARIES, STATS);
+        AmbientBrightnessDayStats identicalDayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
+                BUCKET_BOUNDARIES, STATS);
+        assertEquals(dayStats, identicalDayStats);
+        assertEquals(dayStats.hashCode(), identicalDayStats.hashCode());
+
+        assertNotEquals(emptyDayStats, dayStats);
+        assertNotEquals(emptyDayStats.hashCode(), dayStats.hashCode());
+
+        AmbientBrightnessDayStats differentDateDayStats = new AmbientBrightnessDayStats(
+                LOCAL_DATE.plusDays(1), BUCKET_BOUNDARIES, STATS);
+        assertNotEquals(dayStats, differentDateDayStats);
+        assertNotEquals(dayStats.hashCode(), differentDateDayStats.hashCode());
+
+        float[] differentStats = Arrays.copyOf(STATS, STATS.length);
+        differentStats[differentStats.length - 1] += 5f;
+        AmbientBrightnessDayStats differentStatsDayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
+                BUCKET_BOUNDARIES, differentStats);
+        assertNotEquals(dayStats, differentDateDayStats);
+        assertNotEquals(dayStats.hashCode(), differentStatsDayStats.hashCode());
+
+        float[] differentBucketBoundaries = Arrays.copyOf(BUCKET_BOUNDARIES,
+                BUCKET_BOUNDARIES.length);
+        differentBucketBoundaries[differentBucketBoundaries.length - 1] += 100f;
+        AmbientBrightnessDayStats differentBoundariesDayStats = new AmbientBrightnessDayStats(
+                LOCAL_DATE, differentBucketBoundaries, STATS);
+        assertNotEquals(dayStats, differentBoundariesDayStats);
+        assertNotEquals(dayStats.hashCode(), differentBoundariesDayStats.hashCode());
+    }
+
+    private interface ExceptionRunnable {
+        void run() throws Exception;
+    }
+
+    private static void assertThrows(Class<? extends Throwable> exceptionClass,
+            ExceptionRunnable r) {
+        try {
+            r.run();
+        } catch (Throwable e) {
+            assertTrue("Expected exception type " + exceptionClass.getName() + " but got "
+                    + e.getClass().getName(), exceptionClass.isAssignableFrom(e.getClass()));
+            return;
+        }
+        fail("Expected exception type " + exceptionClass.getName()
+                + ", but no exception was thrown");
+    }
+
 }
diff --git a/docs/html/reference/images/text/style/drawablemarginspan.png b/docs/html/reference/images/text/style/drawablemarginspan.png
new file mode 100644
index 0000000..edf926d
--- /dev/null
+++ b/docs/html/reference/images/text/style/drawablemarginspan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/dynamicdrawablespan.png b/docs/html/reference/images/text/style/dynamicdrawablespan.png
new file mode 100644
index 0000000..8776b03
--- /dev/null
+++ b/docs/html/reference/images/text/style/dynamicdrawablespan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/iconmarginspan.png b/docs/html/reference/images/text/style/iconmarginspan.png
new file mode 100644
index 0000000..8ec39be
--- /dev/null
+++ b/docs/html/reference/images/text/style/iconmarginspan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/imagespan.png b/docs/html/reference/images/text/style/imagespan.png
new file mode 100644
index 0000000..c03e6bb
--- /dev/null
+++ b/docs/html/reference/images/text/style/imagespan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/maskfilterspan.png b/docs/html/reference/images/text/style/maskfilterspan.png
new file mode 100644
index 0000000..6e55dbc
--- /dev/null
+++ b/docs/html/reference/images/text/style/maskfilterspan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/stylespan.png b/docs/html/reference/images/text/style/stylespan.png
new file mode 100644
index 0000000..9ffa05b
--- /dev/null
+++ b/docs/html/reference/images/text/style/stylespan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/tabstopspan.png b/docs/html/reference/images/text/style/tabstopspan.png
new file mode 100644
index 0000000..89a1121
--- /dev/null
+++ b/docs/html/reference/images/text/style/tabstopspan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/typefacespan.png b/docs/html/reference/images/text/style/typefacespan.png
new file mode 100644
index 0000000..67e2cf9
--- /dev/null
+++ b/docs/html/reference/images/text/style/typefacespan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/urlspan.png b/docs/html/reference/images/text/style/urlspan.png
new file mode 100644
index 0000000..1134520
--- /dev/null
+++ b/docs/html/reference/images/text/style/urlspan.png
Binary files differ
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 627d551..69a5874 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -541,10 +541,19 @@
         return mAllowHwBitmapsInSwMode;
     }
 
+    /**
+     * @hide
+     */
+    protected void onHwBitmapInSwMode() {
+        if (!mAllowHwBitmapsInSwMode) {
+            throw new IllegalArgumentException(
+                    "Software rendering doesn't support hardware bitmaps");
+        }
+    }
+
     private void throwIfHwBitmapInSwMode(Bitmap bitmap) {
-        if (!mAllowHwBitmapsInSwMode && !isHardwareAccelerated()
-                && bitmap.getConfig() == Bitmap.Config.HARDWARE) {
-            throw new IllegalStateException("Software rendering doesn't support hardware bitmaps");
+        if (!isHardwareAccelerated() && bitmap.getConfig() == Bitmap.Config.HARDWARE) {
+            onHwBitmapInSwMode();
         }
     }
 
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 0072012..44e7066 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -29,6 +29,10 @@
 import android.os.Trace;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+import android.view.ThreadedRenderer;
+
 import libcore.util.NativeAllocationRegistry;
 
 import java.io.OutputStream;
@@ -1171,6 +1175,82 @@
     }
 
     /**
+     * Creates a Bitmap from the given {@link Picture} source of recorded drawing commands.
+     *
+     * Equivalent to calling {@link #createBitmap(Picture, int, int, Config)} with
+     * width and height the same as the Picture's width and height and a Config.HARDWARE
+     * config.
+     *
+     * @param source The recorded {@link Picture} of drawing commands that will be
+     *               drawn into the returned Bitmap.
+     * @return An immutable bitmap with a HARDWARE config whose contents are created
+     * from the recorded drawing commands in the Picture source.
+     */
+    public static @NonNull Bitmap createBitmap(@NonNull Picture source) {
+        return createBitmap(source, source.getWidth(), source.getHeight(), Config.HARDWARE);
+    }
+
+    /**
+     * Creates a Bitmap from the given {@link Picture} source of recorded drawing commands.
+     *
+     * The bitmap will be immutable with the given width and height. If the width and height
+     * are not the same as the Picture's width & height, the Picture will be scaled to
+     * fit the given width and height.
+     *
+     * @param source The recorded {@link Picture} of drawing commands that will be
+     *               drawn into the returned Bitmap.
+     * @param width The width of the bitmap to create. The picture's width will be
+     *              scaled to match if necessary.
+     * @param height The height of the bitmap to create. The picture's height will be
+     *              scaled to match if necessary.
+     * @param config The {@link Config} of the created bitmap. If this is null then
+     *               the bitmap will be {@link Config#HARDWARE}.
+     *
+     * @return An immutable bitmap with a HARDWARE config whose contents are created
+     * from the recorded drawing commands in the Picture source.
+     */
+    public static @NonNull Bitmap createBitmap(@NonNull Picture source, int width, int height,
+            @NonNull Config config) {
+        if (width <= 0 || height <= 0) {
+            throw new IllegalArgumentException("width & height must be > 0");
+        }
+        if (config == null) {
+            throw new IllegalArgumentException("Config must not be null");
+        }
+        if (source.requiresHardwareAcceleration() && config != Config.HARDWARE) {
+            StrictMode.noteSlowCall("GPU readback");
+        }
+        if (config == Config.HARDWARE || source.requiresHardwareAcceleration()) {
+            final RenderNode node = RenderNode.create("BitmapTemporary", null);
+            node.setLeftTopRightBottom(0, 0, width, height);
+            node.setClipToBounds(false);
+            final DisplayListCanvas canvas = node.start(width, height);
+            if (source.getWidth() != width || source.getHeight() != height) {
+                canvas.scale(width / (float) source.getWidth(),
+                        height / (float) source.getHeight());
+            }
+            canvas.drawPicture(source);
+            node.end(canvas);
+            Bitmap bitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
+            if (config != Config.HARDWARE) {
+                bitmap = bitmap.copy(config, false);
+            }
+            return bitmap;
+        } else {
+            Bitmap bitmap = Bitmap.createBitmap(width, height, config);
+            Canvas canvas = new Canvas(bitmap);
+            if (source.getWidth() != width || source.getHeight() != height) {
+                canvas.scale(width / (float) source.getWidth(),
+                        height / (float) source.getHeight());
+            }
+            canvas.drawPicture(source);
+            canvas.setBitmap(null);
+            bitmap.makeImmutable();
+            return bitmap;
+        }
+    }
+
+    /**
      * Returns an optional array of private data, used by the UI system for
      * some bitmaps. Not intended to be called by applications.
      */
@@ -1259,6 +1339,12 @@
         return mIsMutable;
     }
 
+    /** @hide */
+    public final void makeImmutable() {
+        // todo mIsMutable = false;
+        // todo nMakeImmutable();
+    }
+
     /**
      * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
      * When a pixel is pre-multiplied, the RGB components have been multiplied by
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index 08eeaff..9ac94d8 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -31,8 +31,9 @@
  * be replayed on a hardware accelerated canvas.</p>
  */
 public class Picture {
-    private Canvas mRecordingCanvas;
+    private PictureCanvas mRecordingCanvas;
     private long mNativePicture;
+    private boolean mRequiresHwAcceleration;
 
     private static final int WORKING_STREAM_STORAGE = 16 * 1024;
 
@@ -78,8 +79,12 @@
      * into it.
      */
     public Canvas beginRecording(int width, int height) {
+        if (mRecordingCanvas != null) {
+            throw new IllegalStateException("Picture already recording, must call #endRecording()");
+        }
         long ni = nativeBeginRecording(mNativePicture, width, height);
-        mRecordingCanvas = new RecordingCanvas(this, ni);
+        mRecordingCanvas = new PictureCanvas(this, ni);
+        mRequiresHwAcceleration = false;
         return mRecordingCanvas;
     }
 
@@ -91,6 +96,7 @@
      */
     public void endRecording() {
         if (mRecordingCanvas != null) {
+            mRequiresHwAcceleration = mRecordingCanvas.mHoldsHwBitmap;
             mRecordingCanvas = null;
             nativeEndRecording(mNativePicture);
         }
@@ -113,6 +119,18 @@
     }
 
     /**
+     * Indicates whether or not this Picture contains recorded commands that only work when
+     * drawn to a hardware-accelerated canvas. If this returns true then this Picture can only
+     * be drawn to another Picture or to a Canvas where canvas.isHardwareAccelerated() is true.
+     *
+     * @return true if the Picture can only be drawn to a hardware-accelerated canvas,
+     *         false otherwise.
+     */
+    public boolean requiresHardwareAcceleration() {
+        return mRequiresHwAcceleration;
+    }
+
+    /**
      * Draw this picture on the canvas.
      * <p>
      * Prior to {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this call could
@@ -129,6 +147,9 @@
         if (mRecordingCanvas != null) {
             endRecording();
         }
+        if (mRequiresHwAcceleration && !canvas.isHardwareAccelerated()) {
+            canvas.onHwBitmapInSwMode();
+        }
         nativeDraw(canvas.getNativeCanvasWrapper(), mNativePicture);
     }
 
@@ -164,8 +185,7 @@
         if (stream == null) {
             throw new NullPointerException();
         }
-        if (!nativeWriteToStream(mNativePicture, stream,
-                             new byte[WORKING_STREAM_STORAGE])) {
+        if (!nativeWriteToStream(mNativePicture, stream, new byte[WORKING_STREAM_STORAGE])) {
             throw new RuntimeException();
         }
     }
@@ -182,10 +202,11 @@
                                            OutputStream stream, byte[] storage);
     private static native void nativeDestructor(long nativePicture);
 
-    private static class RecordingCanvas extends Canvas {
+    private static class PictureCanvas extends Canvas {
         private final Picture mPicture;
+        boolean mHoldsHwBitmap;
 
-        public RecordingCanvas(Picture pict, long nativeCanvas) {
+        public PictureCanvas(Picture pict, long nativeCanvas) {
             super(nativeCanvas);
             mPicture = pict;
         }
@@ -202,5 +223,10 @@
             }
             super.drawPicture(picture);
         }
+
+        @Override
+        protected void onHwBitmapInSwMode() {
+            mHoldsHwBitmap = true;
+        }
     }
 }
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index ebc14c8..091b526 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -182,10 +182,11 @@
 
     std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
             std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
-    std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
-            std::vector<minikin::Font>({minikin::Font(std::move(font), minikin::FontStyle())}));
-    std::shared_ptr<minikin::FontCollection> collection =
-            std::make_shared<minikin::FontCollection>(std::move(family));
+    std::vector<minikin::Font> fonts;
+    fonts.push_back(minikin::Font(std::move(font), minikin::FontStyle()));
+
+    std::shared_ptr<minikin::FontCollection> collection = std::make_shared<minikin::FontCollection>(
+            std::make_shared<minikin::FontFamily>(std::move(fonts)));
 
     Typeface* hwTypeface = new Typeface();
     hwTypeface->fFontCollection = collection;
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
index 66d6f52..2232c25 100644
--- a/libs/hwui/tests/unit/TypefaceTests.cpp
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -56,8 +56,9 @@
     LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", fileName);
     std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
             std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
-    return std::make_shared<minikin::FontFamily>(
-            std::vector<minikin::Font>({minikin::Font(std::move(font), minikin::FontStyle())}));
+    std::vector<minikin::Font> fonts;
+    fonts.push_back(minikin::Font(std::move(font), minikin::FontStyle()));
+    return std::make_shared<minikin::FontFamily>(std::move(fonts));
 }
 
 std::vector<std::shared_ptr<minikin::FontFamily>> makeSingleFamlyVector(const char* fileName) {
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 6fe8975..9a66b07 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -94,7 +94,7 @@
                 infile = mFile.openRead();
                 readXml(infile);
             } catch (FileNotFoundException e) {
-                // No data yet
+                Log.d(TAG, "File doesn't exist or isn't readable yet");
             } catch (IOException e) {
                 Log.e(TAG, "Unable to read channel impressions", e);
             } catch (NumberFormatException | XmlPullParserException e) {
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
index 7c35b48..db48f61 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
@@ -325,7 +325,8 @@
         int dismiss2 = 777;
         String key2 = mAssistant.getKey("pkg2", 2, "channel2");
 
-        String xml = "<assistant version=\"1\">\n"
+        String xml = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+                + "<assistant version=\"1\">\n"
                 + "<impression-set key=\"" + key1 + "\" "
                 + "dismisses=\"" + dismiss1 + "\" views=\"" + views1
                 + "\" streak=\"" + streak1 + "\"/>\n"
@@ -377,7 +378,6 @@
         mAssistant.insertImpressions(key2, ci2);
         mAssistant.insertImpressions(key3, ci3);
 
-
         XmlSerializer serializer = new FastXmlSerializer();
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index a9e5adf..cdd417f 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -73,15 +73,18 @@
         android:id="@+id/volume_row_slider_frame"
         android:padding="0dp"
         android:layout_width="@dimen/volume_dialog_panel_width"
+        android:layoutDirection="rtl"
         android:layout_height="150dp">
         <SeekBar
             android:id="@+id/volume_row_slider"
+            android:clickable="true"
             android:padding="0dp"
             android:layout_margin="0dp"
             android:layout_width="150dp"
             android:layout_height="@dimen/volume_dialog_panel_width"
+            android:layoutDirection="rtl"
             android:layout_gravity="center"
-            android:rotation="270" />
+            android:rotation="90" />
     </FrameLayout>
 
     <com.android.keyguard.AlphaOptimizedImageButton
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 653e500..eedc50f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -707,6 +707,9 @@
                     && !mLockPatternUtils.isLockScreenDisabled(
                             KeyguardUpdateMonitor.getCurrentUser()),
                     mSecondaryDisplayShowing, true /* forceCallbacks */);
+        } else {
+            // The system's keyguard is disabled or missing.
+            setShowingLocked(false, mSecondaryDisplayShowing, true);
         }
 
         mStatusBarKeyguardViewManager =
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
index f50a287..4c69594 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUiLayout.java
@@ -133,11 +133,11 @@
         for (int i = 0; i < rowCount; i++) {
             View row = rows.getChildAt(i);
             if (to == ROTATION_SEASCAPE) {
-                rotateSeekBars(row, to, 180);
-            } else if (to == ROTATION_LANDSCAPE) {
                 rotateSeekBars(row, to, 0);
+            } else if (to == ROTATION_LANDSCAPE) {
+                rotateSeekBars(row, to, 180);
             } else {
-                rotateSeekBars(row, to, 270);
+                rotateSeekBars(row, to, 90);
             }
             rotate(row, from, to, true);
         }
@@ -309,12 +309,6 @@
         return super.getOutlineProvider();
     }
 
-    @Override
-    public void setPressed(boolean pressed)
-    {
-        // Ignore presses because it activates the seekbar thumb unnecessarily.
-    }
-
     public void setOutsideTouchListener(OnClickListener onClickListener) {
         mHasOutsideTouch = true;
         requestLayout();
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index f6a54af..c77dcc0 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -63,7 +63,7 @@
   // Number scans that returned at least one result.
   optional int32 num_non_empty_scan_results = 13;
 
-  // Number of scans that were one time.
+  // Number of single scans requests.
   optional int32 num_oneshot_scans = 14;
 
   // Number of repeated background scans that were scheduled to the chip.
@@ -376,6 +376,9 @@
 
   // Wifi power statistics
   optional WifiPowerStats wifi_power_stats = 92;
+
+  // Number of connectivity single scan requests.
+  optional int32 num_connectivity_oneshot_scans = 93;
 }
 
 // Information that gets logged for every WiFi connection.
@@ -1155,4 +1158,4 @@
 
   // Amount of time wifi is in tx (ms)
   optional int64 tx_time_ms = 5;
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ea53dfc..f370393 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4027,9 +4027,13 @@
                 runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
             }
             String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
-            if ("true".equals(genDebugInfoProperty)) {
+            if ("1".equals(genDebugInfoProperty) || "true".equals(genDebugInfoProperty)) {
                 runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
             }
+            String genMiniDebugInfoProperty = SystemProperties.get("dalvik.vm.minidebuginfo");
+            if ("1".equals(genMiniDebugInfoProperty) || "true".equals(genMiniDebugInfoProperty)) {
+                runtimeFlags |= Zygote.DEBUG_GENERATE_MINI_DEBUG_INFO;
+            }
             if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
                 runtimeFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
             }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 502760a..fd435f9 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -771,7 +771,7 @@
      * Called whenever packages change, the user switches, or the secure setting
      * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
      */
-    private void rebindServices(boolean forceRebind) {
+    protected void rebindServices(boolean forceRebind) {
         if (DEBUG) Slog.d(TAG, "rebindServices");
         final int[] userIds = mUserProfiles.getCurrentProfileIds();
         final int nUserIds = userIds.length;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a4ac155..b25124a 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5689,6 +5689,12 @@
             mListeners.unregisterService(removed.service, removed.userid);
         }
 
+        @Override
+        public void onUserUnlocked(int user) {
+            if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user);
+            rebindServices(true);
+        }
+
         public void onNotificationEnqueued(final NotificationRecord r) {
             final StatusBarNotification sbn = r.sbn;
             TrimCache trimCache = new TrimCache(sbn);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 56d4b7e..857925b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -5149,7 +5149,8 @@
                     .forAllShortcuts(si -> {
                         switch (package1DisabledReason) {
                             case ShortcutInfo.DISABLED_REASON_VERSION_LOWER:
-                                assertEquals("This shortcut requires latest app",
+                                assertEquals("App version downgraded, or isn’t compatible"
+                                        + " with this shortcut",
                                         si.getDisabledMessage());
                                 break;
                             case ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH:
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 99eb846..e36586e 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -210,6 +210,9 @@
         runCommand(instrumentation, "cmd package set-home-activity --user "
                 + instrumentation.getContext().getUserId() + " " + component,
                 result -> result.contains("Success"));
+        runCommand(instrumentation, "cmd shortcut clear-default-launcher --user "
+                        + instrumentation.getContext().getUserId(),
+                result -> result.contains("Success"));
     }
 
     public static void setDefaultLauncher(Instrumentation instrumentation, Context packageContext) {
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index dc5ba0c..fe63aa1 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -7,22 +7,21 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
+import android.content.pm.PackageManager;
+import android.net.wifi.rtt.RangingRequest;
+import android.net.wifi.rtt.RangingResult;
+import android.net.wifi.rtt.RangingResultCallback;
+import android.net.wifi.rtt.WifiRttManager;
 import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.RemoteException;
 import android.util.Log;
-import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
+import java.util.List;
+
 /** @hide */
 @SystemApi
 @SystemService(Context.WIFI_RTT_SERVICE)
@@ -175,7 +174,8 @@
     @Deprecated
     @SuppressLint("Doclava125")
     public Capabilities getCapabilities() {
-        return new Capabilities();
+        throw new UnsupportedOperationException(
+                "getCapabilities is not supported in the adaptation layer");
     }
 
     /**
@@ -316,16 +316,7 @@
 
     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
     public RttCapabilities getRttCapabilities() {
-        synchronized (mCapabilitiesLock) {
-            if (mRttCapabilities == null) {
-                try {
-                    mRttCapabilities = mService.getRttCapabilities();
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
-            return mRttCapabilities;
-        }
+        return mRttCapabilities;
     }
 
     /** specifies parameters for RTT request */
@@ -972,69 +963,6 @@
         }
     }
 
-    private boolean rttParamSanity(RttParams params, int index) {
-        if (mRttCapabilities == null) {
-            if(getRttCapabilities() == null) {
-                Log.e(TAG, "Can not get RTT capabilities");
-                throw new IllegalStateException("RTT chip is not working");
-            }
-        }
-
-        if (params.deviceType != RTT_PEER_TYPE_AP) {
-            return false;
-        } else if (params.requestType != RTT_TYPE_ONE_SIDED && params.requestType !=
-                RTT_TYPE_TWO_SIDED) {
-            Log.e(TAG, "Request " + index + ": Illegal Request Type: " + params.requestType);
-            return false;
-        } else if (params.requestType == RTT_TYPE_ONE_SIDED &&
-                !mRttCapabilities.oneSidedRttSupported) {
-            Log.e(TAG, "Request " + index + ": One side RTT is not supported");
-            return false;
-        } else if (params.requestType == RTT_TYPE_TWO_SIDED &&
-                !mRttCapabilities.twoSided11McRttSupported) {
-            Log.e(TAG, "Request " + index + ": two side RTT is not supported");
-            return false;
-        }  else if(params.bssid == null || params.bssid.isEmpty()) {
-            Log.e(TAG,"No BSSID in params");
-            return false;
-        } else if ( params.numberBurst != 0 ) {
-            Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst);
-            return false;
-        } else if (params.numSamplesPerBurst <= 0 || params.numSamplesPerBurst > 31) {
-            Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " +
-                    params.numSamplesPerBurst);
-            return false;
-        } else if (params.numRetriesPerMeasurementFrame < 0 ||
-                params.numRetriesPerMeasurementFrame > 3) {
-            Log.e(TAG, "Request " + index + ": Illegal measurement frame retry number:" +
-                    params.numRetriesPerMeasurementFrame);
-            return false;
-        } else if(params.numRetriesPerFTMR < 0 ||
-                params.numRetriesPerFTMR > 3) {
-            Log.e(TAG, "Request " + index + ": Illegal FTMR frame retry number:" +
-                    params.numRetriesPerFTMR);
-            return false;
-        } else if (params.LCIRequest && !mRttCapabilities.lciSupported) {
-            Log.e(TAG, "Request " + index + ": LCI is not supported");
-            return false;
-        } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) {
-            Log.e(TAG, "Request " + index + ": LCR is not supported");
-            return false;
-        } else if (params.burstTimeout < 1 ||
-                (params.burstTimeout > 11 && params.burstTimeout != 15)){
-            Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout);
-            return false;
-        } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) {
-            Log.e(TAG, "Request " + index + ": Do not support this preamble: " + params.preamble);
-            return false;
-        } else if ((params.bandwidth & mRttCapabilities.bwSupported) == 0) {
-            Log.e(TAG, "Request " + index + ": Do not support this bandwidth: " + params.bandwidth);
-            return false;
-        }
-
-        return true;
-    }
-
     /**
      * Request to start an RTT ranging
      *
@@ -1045,24 +973,72 @@
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startRanging(RttParams[] params, RttListener listener) {
-        int index  = 0;
-        for(RttParams rttParam : params) {
-            if (!rttParamSanity(rttParam, index)) {
-                throw new IllegalArgumentException("RTT Request Parameter Illegal");
-            }
-            index++;
-        }
-        validateChannel();
-        ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
         Log.i(TAG, "Send RTT request to RTT Service");
-        mAsyncChannel.sendMessage(CMD_OP_START_RANGING,
-                0, putListener(listener), parcelableParams);
+
+        if (!mNewService.isAvailable()) {
+            listener.onFailure(REASON_NOT_AVAILABLE, "");
+            return;
+        }
+
+        RangingRequest.Builder builder = new RangingRequest.Builder();
+        for (RttParams rttParams : params) {
+            if (rttParams.deviceType != RTT_PEER_TYPE_AP) {
+                listener.onFailure(REASON_INVALID_REQUEST, "Only AP peers are supported");
+                return;
+            }
+
+            ScanResult reconstructed = new ScanResult();
+            reconstructed.BSSID = rttParams.bssid;
+            if (rttParams.requestType == RTT_TYPE_TWO_SIDED) {
+                reconstructed.setFlag(ScanResult.FLAG_80211mc_RESPONDER);
+            }
+            reconstructed.channelWidth = rttParams.channelWidth;
+            reconstructed.frequency = rttParams.frequency;
+            reconstructed.centerFreq0 = rttParams.centerFreq0;
+            reconstructed.centerFreq1 = rttParams.centerFreq1;
+            builder.addResponder(
+                    android.net.wifi.rtt.ResponderConfig.fromScanResult(reconstructed));
+        }
+        try {
+            mNewService.startRanging(builder.build(), new RangingResultCallback() {
+                @Override
+                public void onRangingFailure(int code) {
+                    int localCode = REASON_UNSPECIFIED;
+                    if (code == STATUS_CODE_FAIL_RTT_NOT_AVAILABLE) {
+                        localCode = REASON_NOT_AVAILABLE;
+                    }
+                    listener.onFailure(localCode, "");
+                }
+
+                @Override
+                public void onRangingResults(List<RangingResult> results) {
+                    RttResult[] legacyResults = new RttResult[results.size()];
+                    int i = 0;
+                    for (RangingResult result : results) {
+                        legacyResults[i] = new RttResult();
+                        legacyResults[i].status = result.getStatus();
+                        legacyResults[i].bssid = result.getMacAddress().toString();
+                        legacyResults[i].distance = result.getDistanceMm() / 10;
+                        legacyResults[i].distanceStandardDeviation =
+                                result.getDistanceStdDevMm() / 10;
+                        legacyResults[i].rssi = result.getRssi();
+                        legacyResults[i].ts = result.getRangingTimestampUs();
+                    }
+                    listener.onSuccess(legacyResults);
+                }
+            }, null);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "startRanging: invalid arguments - " + e);
+            listener.onFailure(REASON_INVALID_REQUEST, e.getMessage());
+        } catch (SecurityException e) {
+            Log.e(TAG, "startRanging: security exception - " + e);
+            listener.onFailure(REASON_PERMISSION_DENIED, e.getMessage());
+        }
     }
 
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void stopRanging(RttListener listener) {
-        validateChannel();
-        mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
+        Log.e(TAG, "stopRanging: unsupported operation - nop");
     }
 
     /**
@@ -1095,12 +1071,8 @@
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void enableResponder(ResponderCallback callback) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback cannot be null");
-        }
-        validateChannel();
-        int key = putListenerIfAbsent(callback);
-        mAsyncChannel.sendMessage(CMD_OP_ENABLE_RESPONDER, 0, key);
+        throw new UnsupportedOperationException(
+                "enableResponder is not supported in the adaptation layer");
     }
 
     /**
@@ -1115,16 +1087,8 @@
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void disableResponder(ResponderCallback callback) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback cannot be null");
-        }
-        validateChannel();
-        int key = removeListener(callback);
-        if (key == INVALID_KEY) {
-            Log.e(TAG, "responder not enabled yet");
-            return;
-        }
-        mAsyncChannel.sendMessage(CMD_OP_DISABLE_RESPONDER, 0, key);
+        throw new UnsupportedOperationException(
+                "disableResponder is not supported in the adaptation layer");
     }
 
     /**
@@ -1238,17 +1202,9 @@
     /** @hide */
     public static final int CMD_OP_REG_BINDER           = BASE + 9;
 
-    private static final int INVALID_KEY = 0;
-
     private final Context mContext;
-    private final IRttManager mService;
-    private final SparseArray mListenerMap = new SparseArray();
-    private final Object mListenerMapLock = new Object();
-    private final Object mCapabilitiesLock = new Object();
-
+    private final WifiRttManager mNewService;
     private RttCapabilities mRttCapabilities;
-    private int mListenerKey = 1;
-    private AsyncChannel mAsyncChannel;
 
     /**
      * Create a new WifiScanner instance.
@@ -1263,170 +1219,20 @@
      */
     public RttManager(Context context, IRttManager service, Looper looper) {
         mContext = context;
-        mService = service;
-        Messenger messenger = null;
-        int[] key = new int[1];
-        try {
-            Log.d(TAG, "Get the messenger from " + mService);
-            messenger = mService.getMessenger(new Binder(), key);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        mNewService = (WifiRttManager) mContext.getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
 
-        if (messenger == null) {
-            throw new IllegalStateException("getMessenger() returned null!  This is invalid.");
-        }
+        boolean rttSupported = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_WIFI_RTT);
 
-        mAsyncChannel = new AsyncChannel();
-
-        Handler handler = new ServiceHandler(looper);
-        mAsyncChannel.connectSync(mContext, handler, messenger);
-        // We cannot use fullyConnectSync because it sends the FULL_CONNECTION message
-        // synchronously, which causes RttService to receive the wrong replyTo value.
-        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION,
-                new RttClient(context.getPackageName()));
-        mAsyncChannel.sendMessage(CMD_OP_REG_BINDER, key[0]);
+        mRttCapabilities = new RttCapabilities();
+        mRttCapabilities.oneSidedRttSupported = rttSupported;
+        mRttCapabilities.twoSided11McRttSupported = rttSupported;
+        mRttCapabilities.lciSupported = false;
+        mRttCapabilities.lcrSupported = false;
+        mRttCapabilities.preambleSupported = PREAMBLE_HT | PREAMBLE_VHT;
+        mRttCapabilities.bwSupported = RTT_BW_40_SUPPORT | RTT_BW_80_SUPPORT;
+        mRttCapabilities.responderSupported = false;
+        mRttCapabilities.secureRttSupported = false;
     }
-
-    private void validateChannel() {
-        if (mAsyncChannel == null) throw new IllegalStateException(
-                "No permission to access and change wifi or a bad initialization");
-    }
-
-    private int putListener(Object listener) {
-        if (listener == null) return INVALID_KEY;
-        int key;
-        synchronized (mListenerMapLock) {
-            do {
-                key = mListenerKey++;
-            } while (key == INVALID_KEY);
-            mListenerMap.put(key, listener);
-        }
-        return key;
-    }
-
-    // Insert a listener if it doesn't exist in mListenerMap. Returns the key of the listener.
-    private int putListenerIfAbsent(Object listener) {
-        if (listener == null) return INVALID_KEY;
-        synchronized (mListenerMapLock) {
-            int key = getListenerKey(listener);
-            if (key != INVALID_KEY) {
-                return key;
-            }
-            do {
-                key = mListenerKey++;
-            } while (key == INVALID_KEY);
-            mListenerMap.put(key, listener);
-            return key;
-        }
-
-    }
-
-    private Object getListener(int key) {
-        if (key == INVALID_KEY) return null;
-        synchronized (mListenerMapLock) {
-            Object listener = mListenerMap.get(key);
-            return listener;
-        }
-    }
-
-    private int getListenerKey(Object listener) {
-        if (listener == null) return INVALID_KEY;
-        synchronized (mListenerMapLock) {
-            int index = mListenerMap.indexOfValue(listener);
-            if (index == -1) {
-                return INVALID_KEY;
-            } else {
-                return mListenerMap.keyAt(index);
-            }
-        }
-    }
-
-    private Object removeListener(int key) {
-        if (key == INVALID_KEY) return null;
-        synchronized (mListenerMapLock) {
-            Object listener = mListenerMap.get(key);
-            mListenerMap.remove(key);
-            return listener;
-        }
-    }
-
-    private int removeListener(Object listener) {
-        int key = getListenerKey(listener);
-        if (key == INVALID_KEY) return key;
-        synchronized (mListenerMapLock) {
-            mListenerMap.remove(key);
-            return key;
-        }
-    }
-
-    private class ServiceHandler extends Handler {
-        ServiceHandler(Looper looper) {
-            super(looper);
-        }
-        @Override
-        public void handleMessage(Message msg) {
-            Log.i(TAG, "RTT manager get message: " + msg.what);
-            switch (msg.what) {
-                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
-                    return;
-                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                    Log.e(TAG, "Channel connection lost");
-                    // This will cause all further async API calls on the WifiManager
-                    // to fail and throw an exception
-                    mAsyncChannel = null;
-                    getLooper().quit();
-                    return;
-            }
-
-            Object listener = getListener(msg.arg2);
-            if (listener == null) {
-                Log.e(TAG, "invalid listener key = " + msg.arg2 );
-                return;
-            } else {
-                Log.i(TAG, "listener key = " + msg.arg2);
-            }
-
-            switch (msg.what) {
-                /* ActionListeners grouped together */
-                case CMD_OP_SUCCEEDED :
-                    reportSuccess(listener, msg);
-                    removeListener(msg.arg2);
-                    break;
-                case CMD_OP_FAILED :
-                    reportFailure(listener, msg);
-                    removeListener(msg.arg2);
-                    break;
-                case CMD_OP_ABORTED :
-                    ((RttListener) listener).onAborted();
-                    removeListener(msg.arg2);
-                    break;
-                case CMD_OP_ENALBE_RESPONDER_SUCCEEDED:
-                    ResponderConfig config = (ResponderConfig) msg.obj;
-                    ((ResponderCallback) (listener)).onResponderEnabled(config);
-                    break;
-                case CMD_OP_ENALBE_RESPONDER_FAILED:
-                    ((ResponderCallback) (listener)).onResponderEnableFailure(msg.arg1);
-                    removeListener(msg.arg2);
-                    break;
-                default:
-                    if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
-                    return;
-            }
-        }
-
-        void reportSuccess(Object listener, Message msg) {
-            RttListener rttListener = (RttListener) listener;
-            ParcelableRttResults parcelableResults = (ParcelableRttResults) msg.obj;
-            ((RttListener) listener).onSuccess(parcelableResults.mResults);
-        }
-
-        void reportFailure(Object listener, Message msg) {
-            RttListener rttListener = (RttListener) listener;
-            Bundle bundle = (Bundle) msg.obj;
-            ((RttListener) listener).onFailure(msg.arg1, bundle.getString(DESCRIPTION_KEY));
-        }
-    }
-
 }