Merge "Add new internal API: enableOptionalCodecs()/disableOptionalCodecs()"
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index d36c0d6..3e13ad3 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -253,10 +253,10 @@
         /**
          * Set whether the advertisement type should be connectable or
          * non-connectable.
-         * Legacy advertisements can be both connectable and scannable. Other
-         * advertisements can be connectable only if not scannable.
+         * Legacy advertisements must be both connectable and scannable. Nonlegacy
+         * advertisements can be only scannable or only connectable.
          * @param connectable Controls whether the advertisment type will be
-         * connectable (true) or non-connectable (false).
+         * connectable (true) or nonconnectable (false).
          */
         public Builder setConnectable(boolean connectable) {
             this.connectable = connectable;
@@ -264,11 +264,11 @@
         }
 
         /**
-         * Set whether the advertisement type should be scannable
-         * Legacy advertisements can be both connectable and scannable. Other
-         * advertisements can be scannable only if not connectable.
+         * Set whether the advertisement type should be scannable.
+         * Legacy advertisements must be both connectable and scannable. Nonlegacy
+         * advertisements can be only scannable or only connectable.
          * @param scannable Controls whether the advertisment type will be
-         * scannable (true) or non-scannable (false).
+         * scannable (true) or nonscannable (false).
          */
         public Builder setScannable(boolean scannable) {
             this.scannable = scannable;
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 3ac6019..4f4152c 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -728,6 +728,10 @@
             int timeTotal = -1;
             int uncryptTime = -1;
             int sourceVersion = -1;
+            int temperature_start = -1;
+            int temperature_end = -1;
+            int temperature_max = -1;
+
             while ((line = in.readLine()) != null) {
                 // Here is an example of lines in last_install:
                 // ...
@@ -772,6 +776,12 @@
                 } else if (line.startsWith("bytes_stashed")) {
                     bytesStashedInMiB = (bytesStashedInMiB == -1) ? scaled :
                             bytesStashedInMiB + scaled;
+                } else if (line.startsWith("temperature_start")) {
+                    temperature_start = scaled;
+                } else if (line.startsWith("temperature_end")) {
+                    temperature_end = scaled;
+                } else if (line.startsWith("temperature_max")) {
+                    temperature_max = scaled;
                 }
             }
 
@@ -791,6 +801,15 @@
             if (bytesStashedInMiB != -1) {
                 MetricsLogger.histogram(context, "ota_stashed_in_MiBs", bytesStashedInMiB);
             }
+            if (temperature_start != -1) {
+                MetricsLogger.histogram(context, "ota_temperature_start", temperature_start);
+            }
+            if (temperature_end != -1) {
+                MetricsLogger.histogram(context, "ota_temperature_end", temperature_end);
+            }
+            if (temperature_max != -1) {
+                MetricsLogger.histogram(context, "ota_temperature_max", temperature_max);
+            }
 
         } catch (IOException e) {
             Log.e(TAG, "Failed to read lines in last_install", e);
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index d67cef3..8d9630f 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -2070,8 +2070,6 @@
      * @param args
      */
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        // Cannot just invoke pw.println(this.toString()) because if the
-        // resulting string is to long it won't be displayed.
         pw.println(getName() + ":");
         pw.println(" total records=" + getLogRecCount());
         for (int i = 0; i < getLogRecSize(); i++) {
@@ -2083,12 +2081,15 @@
 
     @Override
     public String toString() {
-        StringWriter sr = new StringWriter();
-        PrintWriter pr = new PrintWriter(sr);
-        dump(null, pr, null);
-        pr.flush();
-        pr.close();
-        return sr.toString();
+        String name = "(null)";
+        String state = "(null)";
+        try {
+            name = mName.toString();
+            state = mSmHandler.getCurrentState().getName().toString();
+        } catch (NullPointerException npe) {
+            // Will use default(s) initialized above.
+        }
+        return "name=" + name + " state=" + state;
     }
 
     /**
diff --git a/core/tests/utiltests/runtests.sh b/core/tests/utiltests/runtests.sh
new file mode 100755
index 0000000..853119f
--- /dev/null
+++ b/core/tests/utiltests/runtests.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+  echo "You need to source and lunch before you can use this script"
+  exit 1
+fi
+
+echo "Running tests"
+
+set -e # fail early
+
+echo "+ mmma -j32 $ANDROID_BUILD_TOP/frameworks/base/core/tests/utiltests"
+# NOTE Don't actually run the command above since this shell doesn't inherit functions from the
+#      caller.
+make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk MODULES-IN-frameworks-base-core-tests-utiltests
+
+set -x # print commands
+
+adb root
+adb wait-for-device
+
+adb install -r -g "$OUT/data/app/FrameworksUtilTests/FrameworksUtilTests.apk"
+
+adb shell am instrument -w "$@" 'com.android.frameworks.utiltests/android.support.test.runner.AndroidJUnitRunner'
diff --git a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
index d29b572..eb2a516 100644
--- a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
@@ -80,6 +80,66 @@
     }
 
     /**
+     * Tests {@link StateMachine#toString()}.
+     */
+    class StateMachineToStringTest extends StateMachine {
+        StateMachineToStringTest(String name) {
+            super(name);
+        }
+    }
+
+    class ExampleState extends State {
+        String mName;
+
+        ExampleState(String name) {
+            mName = name;
+        }
+
+        @Override
+        public String getName() {
+            return mName;
+        }
+    }
+
+    @SmallTest
+    public void testToStringSucceedsEvenIfMachineHasNoStates() throws Exception {
+        StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
+        assertTrue(stateMachine.toString().contains("TestStateMachine"));
+    }
+
+    @SmallTest
+    public void testToStringSucceedsEvenIfStateHasNoName() throws Exception {
+        StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
+        State exampleState = new ExampleState(null);
+        stateMachine.addState(exampleState);
+        stateMachine.setInitialState(exampleState);
+        stateMachine.start();
+        assertTrue(stateMachine.toString().contains("TestStateMachine"));
+        assertTrue(stateMachine.toString().contains("(null)"));
+    }
+
+    @SmallTest
+    public void testToStringIncludesMachineAndStateNames() throws Exception {
+        StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
+        State exampleState = new ExampleState("exampleState");
+        stateMachine.addState(exampleState);
+        stateMachine.setInitialState(exampleState);
+        stateMachine.start();
+        assertTrue(stateMachine.toString().contains("TestStateMachine"));
+        assertTrue(stateMachine.toString().contains("exampleState"));
+    }
+
+    @SmallTest
+    public void testToStringDoesNotContainMultipleLines() throws Exception {
+        StateMachine stateMachine = new StateMachineToStringTest("TestStateMachine");
+        State exampleState = new ExampleState("exampleState");
+        stateMachine.addState(exampleState);
+        stateMachine.setInitialState(exampleState);
+        stateMachine.start();
+        assertFalse(stateMachine.toString().contains("\n"));
+    }
+
+    /**
      * Tests {@link StateMachine#quit()}.
      */
     class StateMachineQuitTest extends StateMachine {
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index 8c18c46..0412db5 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -20,6 +20,8 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
+import android.os.SystemClock;
+import android.util.Slog;
 import android.view.WindowManager;
 import android.widget.Toast;
 
@@ -31,10 +33,12 @@
  */
 public class LockTaskNotify {
     private static final String TAG = "LockTaskNotify";
+    private static final long SHOW_TOAST_MINIMUM_INTERVAL = 1000;
 
     private final Context mContext;
     private final H mHandler;
     private Toast mLastToast;
+    private long mLastShowToastTime;
 
     public LockTaskNotify(Context context) {
         mContext = context;
@@ -55,10 +59,16 @@
         if (text == null) {
             return;
         }
+        long showToastTime = SystemClock.elapsedRealtime();
+        if ((showToastTime - mLastShowToastTime) < SHOW_TOAST_MINIMUM_INTERVAL) {
+            Slog.i(TAG, "Ignore toast since it is requested in very short interval.");
+            return;
+        }
         if (mLastToast != null) {
             mLastToast.cancel();
         }
         mLastToast = makeAllUserToastAndShow(text);
+        mLastShowToastTime = showToastTime;
     }
 
     public void show(boolean starting) {