Merge "Retain display when creating specialized contexts. (DO NOT MERGE)" into klp-modular-dev
diff --git a/api/current.txt b/api/current.txt
index 67eb6ea..5a378e2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6448,6 +6448,7 @@
     field public static final java.lang.String CATEGORY_HOME = "android.intent.category.HOME";
     field public static final java.lang.String CATEGORY_INFO = "android.intent.category.INFO";
     field public static final java.lang.String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER";
+    field public static final java.lang.String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
     field public static final java.lang.String CATEGORY_LE_DESK_DOCK = "android.intent.category.LE_DESK_DOCK";
     field public static final java.lang.String CATEGORY_MONKEY = "android.intent.category.MONKEY";
     field public static final java.lang.String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 11ac15f..590ccf89 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2765,6 +2765,12 @@
     @SdkConstant(SdkConstantType.INTENT_CATEGORY)
     public static final String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER";
     /**
+     * Indicates an activity optimized for Leanback mode, and that should
+     * be displayed in the Leanback launcher.
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
+    /**
      * Provides information about the package it is in; typically used if
      * a package does not contain a {@link #CATEGORY_LAUNCHER} to provide
      * a front-door to the user without having to be shown in the all apps list.
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 6650fca..5d55143 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -21,11 +21,11 @@
 /**
  * Class that operates the vibrator on the device.
  * <p>
- * If your process exits, any vibration you started with will stop.
+ * If your process exits, any vibration you started will stop.
  * </p>
  *
  * To obtain an instance of the system vibrator, call
- * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as argument.
+ * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as the argument.
  */
 public abstract class Vibrator {
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b0bae46..9b47cbe 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16499,7 +16499,7 @@
             } else {
                 long value = mMeasureCache.valueAt(cacheIndex);
                 // Casting a long to int drops the high 32 bits, no mask needed
-                setMeasuredDimension((int) (value >> 32), (int) value);
+                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
             }
 
@@ -16594,6 +16594,22 @@
             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
             measuredHeight += optical ? opticalHeight : -opticalHeight;
         }
+        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
+    }
+
+    /**
+     * Sets the measured dimension without extra processing for things like optical bounds.
+     * Useful for reapplying consistent values that have already been cooked with adjustments
+     * for optical bounds, etc. such as those from the measurement cache.
+     *
+     * @param measuredWidth The measured width of this view.  May be a complex
+     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
+     * {@link #MEASURED_STATE_TOO_SMALL}.
+     * @param measuredHeight The measured height of this view.  May be a complex
+     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
+     * {@link #MEASURED_STATE_TOO_SMALL}.
+     */
+    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
         mMeasuredWidth = measuredWidth;
         mMeasuredHeight = measuredHeight;
 
@@ -18361,7 +18377,18 @@
         }
 
         static int adjust(int measureSpec, int delta) {
-            return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec));
+            final int mode = getMode(measureSpec);
+            if (mode == UNSPECIFIED) {
+                // No need to adjust size for UNSPECIFIED mode.
+                return makeMeasureSpec(0, UNSPECIFIED);
+            }
+            int size = getSize(measureSpec) + delta;
+            if (size < 0) {
+                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
+                        ") spec: " + toString(measureSpec) + " delta: " + delta);
+                size = 0;
+            }
+            return makeMeasureSpec(size, mode);
         }
 
         /**
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index cc8ce2c..467d42e 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -126,6 +126,20 @@
                 mVelocityTracker.addMovement(ev);
                 break;
 
+            case MotionEvent.ACTION_POINTER_DOWN:
+                int actionIndex = ev.getActionIndex();
+                mActiveTouchId = ev.getPointerId(actionIndex);
+                break;
+            case MotionEvent.ACTION_POINTER_UP:
+                actionIndex = ev.getActionIndex();
+                int pointerId = ev.getPointerId(actionIndex);
+                if (pointerId == mActiveTouchId) {
+                    // This was our active pointer going up. Choose a new active pointer.
+                    int newActionIndex = actionIndex == 0 ? 1 : 0;
+                    mActiveTouchId = ev.getPointerId(newActionIndex);
+                }
+                break;
+
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
                 resetMembers();
@@ -137,6 +151,11 @@
                 }
 
                 int pointerIndex = ev.findPointerIndex(mActiveTouchId);
+                if (pointerIndex == -1) {
+                    Log.e(TAG, "Invalid pointer index: ignoring.");
+                    mDiscardIntercept = true;
+                    break;
+                }
                 float dx = ev.getRawX() - mDownX;
                 float x = ev.getX(pointerIndex);
                 float y = ev.getY(pointerIndex);
@@ -228,11 +247,11 @@
     }
 
     private void updateDismiss(MotionEvent ev) {
+        float deltaX = ev.getRawX() - mDownX;
         if (!mDismissed) {
             mVelocityTracker.addMovement(ev);
             mVelocityTracker.computeCurrentVelocity(1000);
 
-            float deltaX = ev.getRawX() - mDownX;
             float velocityX = mVelocityTracker.getXVelocity();
             float absVelocityX = Math.abs(velocityX);
             float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
@@ -247,6 +266,13 @@
                 mDismissed = true;
             }
         }
+        // Check if the user tried to undo this.
+        if (mDismissed && mSwiping) {
+            // Check if the user's finger is actually back
+            if (deltaX < getWidth() / 2) {
+                mDismissed = false;
+            }
+        }
     }
 
     /**
diff --git a/data/keyboards/AVRCP.kl b/data/keyboards/AVRCP.kl
index 4c91ece..736b43c 100644
--- a/data/keyboards/AVRCP.kl
+++ b/data/keyboards/AVRCP.kl
@@ -14,8 +14,8 @@
 
 # Key layout used for Bluetooth AVRCP support.
 
-key 200   MEDIA_PLAY_PAUSE    WAKE
-key 201   MEDIA_PLAY_PAUSE    WAKE
+key 200   MEDIA_PLAY          WAKE
+key 201   MEDIA_PAUSE         WAKE
 key 166   MEDIA_STOP          WAKE
 key 163   MEDIA_NEXT          WAKE
 key 165   MEDIA_PREVIOUS      WAKE
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index b6a4899..0cdcb1c 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -423,3 +423,16 @@
 axis 0x0a BRAKE
 axis 0x10 HAT_X
 axis 0x11 HAT_Y
+
+# LEDs
+led 0x00 NUM_LOCK
+led 0x01 CAPS_LOCK
+led 0x02 SCROLL_LOCK
+led 0x03 COMPOSE
+led 0x04 KANA
+led 0x05 SLEEP
+led 0x06 SUSPEND
+led 0x07 MUTE
+led 0x08 MISC
+led 0x09 MAIL
+led 0x0a CHARGING
diff --git a/docs/html/google/auth/api-client.jd b/docs/html/google/auth/api-client.jd
index fda3310..402a95f 100644
--- a/docs/html/google/auth/api-client.jd
+++ b/docs/html/google/auth/api-client.jd
@@ -112,7 +112,7 @@
 href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html"
 >{@code ConnectionCallbacks}</a> and <a
 href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.OnConnectionFailedListener.html"
->{@code onConnectionFailedListener}</a>. These interfaces receive callbacks in
+>{@code OnConnectionFailedListener}</a>. These interfaces receive callbacks in
 response to the asynchronous <a
 href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()"
 >{@code connect()}</a> method when the connection to Google Play services
@@ -512,7 +512,7 @@
     new GetFileTask().execute(filename);
 }
 
-private class GetFileTask extends AsyncTask<String, Void, Void> {
+private class GetFileTask extends AsyncTask&lt;String, Void, Void> {
     protected void doInBackground(String filename) {
         Query query = new Query.Builder()
                 .addFilter(Filters.eq(SearchableField.TITLE, filename))
diff --git a/docs/html/guide/topics/ui/controls/button.jd b/docs/html/guide/topics/ui/controls/button.jd
index 41b67b7f..cb274ae 100644
--- a/docs/html/guide/topics/ui/controls/button.jd
+++ b/docs/html/guide/topics/ui/controls/button.jd
@@ -113,7 +113,7 @@
 
 <h3 id="ClickListener">Using an OnClickListener</h3>
 
-<p>You can also declare the click event handler pragmatically rather than in an XML layout. This
+<p>You can also declare the click event handler programmatically rather than in an XML layout. This
 might be necessary if you instantiate the {@link android.widget.Button} at runtime or you need to
 declare the click behavior in a {@link android.app.Fragment} subclass.</p>
 
diff --git a/docs/html/guide/topics/ui/controls/togglebutton.jd b/docs/html/guide/topics/ui/controls/togglebutton.jd
index 3119cd9..5e2a551 100644
--- a/docs/html/guide/topics/ui/controls/togglebutton.jd
+++ b/docs/html/guide/topics/ui/controls/togglebutton.jd
@@ -99,7 +99,7 @@
 
 <h3 id="ClickListener">Using an OnCheckedChangeListener</h3>
 
-<p>You can also declare a click event handler pragmatically rather than in an XML layout. This
+<p>You can also declare a click event handler programmatically rather than in an XML layout. This
 might be necessary if you instantiate the {@link android.widget.ToggleButton} or {@link
 android.widget.Switch} at runtime or you need to
 declare the click behavior in a {@link android.app.Fragment} subclass.</p>
diff --git a/libs/input/EventHub.cpp b/libs/input/EventHub.cpp
index fc64656..0f1da51 100644
--- a/libs/input/EventHub.cpp
+++ b/libs/input/EventHub.cpp
@@ -509,8 +509,9 @@
 bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
-    if (device && led >= 0 && led <= LED_MAX) {
-        if (test_bit(led, device->ledBitmask)) {
+    int32_t sc;
+    if (device && mapLed(device, led, &sc) == NO_ERROR) {
+        if (test_bit(sc, device->ledBitmask)) {
             return true;
         }
     }
@@ -520,12 +521,17 @@
 void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
-    if (device && !device->isVirtual() && led >= 0 && led <= LED_MAX) {
+    setLedStateLocked(device, led, on);
+}
+
+void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) {
+    int32_t sc;
+    if (device && !device->isVirtual() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
         struct input_event ev;
         ev.time.tv_sec = 0;
         ev.time.tv_usec = 0;
         ev.type = EV_LED;
-        ev.code = led;
+        ev.code = sc;
         ev.value = on ? 1 : 0;
 
         ssize_t nWrite;
@@ -1239,6 +1245,7 @@
 
     if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_GAMEPAD)) {
         device->controllerNumber = getNextControllerNumberLocked(device);
+        setLedForController(device);
     }
 
     // Register with epoll.
@@ -1378,6 +1385,11 @@
     mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
 }
 
+void EventHub::setLedForController(Device* device) {
+    for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
+        setLedStateLocked(device, ALED_CONTROLLER_1 + i, device->controllerNumber == i + 1);
+    }
+}
 
 bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
     if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
@@ -1397,6 +1409,21 @@
     return false;
 }
 
+status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) const {
+    if (!device->keyMap.haveKeyLayout() || !device->ledBitmask) {
+        return NAME_NOT_FOUND;
+    }
+
+    int32_t scanCode;
+    if(device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
+        if(scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) {
+            *outScanCode = scanCode;
+            return NO_ERROR;
+        }
+    }
+    return NAME_NOT_FOUND;
+}
+
 status_t EventHub::closeDeviceByPathLocked(const char *devicePath) {
     Device* device = getDeviceByPathLocked(devicePath);
     if (device) {
diff --git a/libs/input/EventHub.h b/libs/input/EventHub.h
index ae28f01..0d63849 100644
--- a/libs/input/EventHub.h
+++ b/libs/input/EventHub.h
@@ -231,6 +231,8 @@
             uint8_t* outFlags) const = 0;
 
     virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
+
+    /* LED related functions expect Android LED constants, not scan codes or HID usages */
     virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
     virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
 
@@ -393,6 +395,10 @@
 
     int32_t getNextControllerNumberLocked(Device* device);
     void releaseControllerNumberLocked(Device* device);
+    void setLedForController(Device* device);
+
+    status_t mapLed(Device* device, int32_t led, int32_t* outScanCode) const;
+    void setLedStateLocked(Device* device, int32_t led, bool on);
 
     // Protect all internal state.
     mutable Mutex mLock;
diff --git a/libs/input/InputReader.cpp b/libs/input/InputReader.cpp
index b1b7c7d..d4e1a00 100644
--- a/libs/input/InputReader.cpp
+++ b/libs/input/InputReader.cpp
@@ -2197,9 +2197,9 @@
 }
 
 void KeyboardInputMapper::resetLedState() {
-    initializeLedState(mCapsLockLedState, LED_CAPSL);
-    initializeLedState(mNumLockLedState, LED_NUML);
-    initializeLedState(mScrollLockLedState, LED_SCROLLL);
+    initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
+    initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
+    initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
 
     updateLedState(true);
 }
@@ -2210,11 +2210,11 @@
 }
 
 void KeyboardInputMapper::updateLedState(bool reset) {
-    updateLedStateForModifier(mCapsLockLedState, LED_CAPSL,
+    updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK,
             AMETA_CAPS_LOCK_ON, reset);
-    updateLedStateForModifier(mNumLockLedState, LED_NUML,
+    updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK,
             AMETA_NUM_LOCK_ON, reset);
-    updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL,
+    updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK,
             AMETA_SCROLL_LOCK_ON, reset);
 }
 
diff --git a/services/core/java/com/android/server/wifi/WifiController.java b/services/core/java/com/android/server/wifi/WifiController.java
index a3d514e..bdb0a5e 100644
--- a/services/core/java/com/android/server/wifi/WifiController.java
+++ b/services/core/java/com/android/server/wifi/WifiController.java
@@ -152,11 +152,21 @@
             addState(mStaDisabledWithScanState, mDefaultState);
             addState(mApEnabledState, mDefaultState);
             addState(mEcmState, mDefaultState);
-        if (mSettingsStore.isScanAlwaysAvailable()) {
+
+        boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
+        boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
+        boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
+
+        log("isAirplaneModeOn = " + isAirplaneModeOn +
+                ", isWifiEnabled = " + isWifiEnabled +
+                ", isScanningAvailable = " + isScanningAlwaysAvailable);
+
+        if (isWifiEnabled && isScanningAlwaysAvailable) {
             setInitialState(mStaDisabledWithScanState);
         } else {
             setInitialState(mApStaDisabledState);
         }
+
         setLogRecSize(100);
         setLogOnlyTransitions(false);
 
diff --git a/services/core/java/com/android/server/wifi/WifiService.java b/services/core/java/com/android/server/wifi/WifiService.java
index f2efde1..aecf9ae 100644
--- a/services/core/java/com/android/server/wifi/WifiService.java
+++ b/services/core/java/com/android/server/wifi/WifiService.java
@@ -870,7 +870,7 @@
     public void setCountryCode(String countryCode, boolean persist) {
         Slog.i(TAG, "WifiService trying to set country code to " + countryCode +
                 " with persist set to " + persist);
-        enforceChangePermission();
+        enforceConnectivityInternalPermission();
         final long token = Binder.clearCallingIdentity();
         try {
             mWifiStateMachine.setCountryCode(countryCode, persist);
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 69d3efe..cf1669c 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -233,6 +233,10 @@
     private DhcpStateMachine mDhcpStateMachine;
     private boolean mDhcpActive = false;
 
+    // Delay in switching to null country code (non-null has no delay)
+    private final int COUNTRY_CODE_DELAY_MS = 15000;
+    private final AtomicInteger mCountryCodeSequence = new AtomicInteger();
+
     private class InterfaceObserver extends BaseNetworkObserver {
         private WifiStateMachine mWifiStateMachine;
 
@@ -1535,14 +1539,15 @@
      * @param persist {@code true} if the setting should be remembered.
      */
     public void setCountryCode(String countryCode, boolean persist) {
-        if (persist) {
-            mPersistedCountryCode = countryCode;
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.WIFI_COUNTRY_CODE,
-                    countryCode);
+        // If it's a country code, apply immediately,
+        // If it's empty, delay it in case it's a momentary dropout
+        int countryCodeSequence = mCountryCodeSequence.incrementAndGet();
+        if (TextUtils.isEmpty(countryCode)) {
+            sendMessageDelayed(CMD_SET_COUNTRY_CODE, countryCodeSequence, persist ? 1 : 0,
+                    countryCode, COUNTRY_CODE_DELAY_MS);
+        } else {
+            sendMessage(CMD_SET_COUNTRY_CODE, countryCodeSequence, persist ? 1 : 0, countryCode);
         }
-        sendMessage(CMD_SET_COUNTRY_CODE, countryCode);
-        mWifiP2pChannel.sendMessage(WifiP2pService.SET_COUNTRY_CODE, countryCode);
     }
 
     /**
@@ -2508,7 +2513,9 @@
                         // to the driver happened between mPersistedCountryCode getting set
                         // and now, so simply persisting it here would mean we have sent
                         // nothing to the driver.  Send the cmd so it might be set now.
-                        sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE, countryCode);
+                        int sequenceNum = mCountryCodeSequence.incrementAndGet();
+                        sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE,
+                                sequenceNum, 0, countryCode);
                     }
                     break;
                 case CMD_SET_BATCHED_SCAN:
@@ -3091,18 +3098,29 @@
                     break;
                 case CMD_SET_COUNTRY_CODE:
                     String country = (String) message.obj;
+                    final boolean persist = (message.arg2 == 1);
+                    final int sequence = message.arg1;
+                    if (sequence != mCountryCodeSequence.get()) {
+                        if (DBG) log("set country code ignored due to sequence num");
+                        break;
+                    }
                     if (DBG) log("set country code " + country);
-                    if (country != null) {
-                        country = country.toUpperCase(Locale.ROOT);
-                        if (mLastSetCountryCode == null
-                                || country.equals(mLastSetCountryCode) == false) {
-                            if (mWifiNative.setCountryCode(country)) {
-                                mLastSetCountryCode = country;
-                            } else {
-                                loge("Failed to set country code " + country);
-                            }
+                    if (persist) {
+                        mPersistedCountryCode = country;
+                        Settings.Global.putString(mContext.getContentResolver(),
+                                Settings.Global.WIFI_COUNTRY_CODE,
+                                country);
+                    }
+                    country = country.toUpperCase(Locale.ROOT);
+                    if (mLastSetCountryCode == null
+                            || country.equals(mLastSetCountryCode) == false) {
+                        if (mWifiNative.setCountryCode(country)) {
+                            mLastSetCountryCode = country;
+                        } else {
+                            loge("Failed to set country code " + country);
                         }
                     }
+                    mWifiP2pChannel.sendMessage(WifiP2pService.SET_COUNTRY_CODE, country);
                     break;
                 case CMD_SET_FREQUENCY_BAND:
                     int band =  message.arg1;