Merge "Fix bug 4807086 - Options menu panel too narrow in landscape"
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 2b9c082..9bab797 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -82,11 +82,8 @@
     /* Clears default preferences and permissions for the package */
     void clearDefaults(String packageName);
 
-    /* Sets the current primary USB function. */
-    void setPrimaryFunction(String functions);
-
-    /* Sets the default primary USB function. */
-    void setDefaultFunction(String functions);
+    /* Sets the current USB function. */
+    void setCurrentFunction(String function, boolean makeDefault);
 
     /* Sets the file path for USB mass storage backing file. */
     void setMassStorageBackingFile(String path);
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index a828a23..67d200c 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -408,32 +408,18 @@
     }
 
     /**
-     * Sets the primary USB function.
+     * Sets the current USB function.
      *
      * @param function name of the USB function
+     * @param makeDefault true if this should be set as the default
      *
      * {@hide}
      */
-    public void setPrimaryFunction(String function) {
+    public void setCurrentFunction(String function, boolean makeDefault) {
         try {
-            mService.setPrimaryFunction(function);
+            mService.setCurrentFunction(function, makeDefault);
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setPrimaryFunction", e);
-        }
-    }
-
-    /**
-     * Sets the default primary USB function.
-     *
-     * @param function name of the USB function
-     *
-     * {@hide}
-     */
-    public void setDefaultFunction(String function) {
-        try {
-            mService.setDefaultFunction(function);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setDefaultFunction", e);
+            Log.e(TAG, "RemoteException in setCurrentFunction", e);
         }
     }
 
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 0e52869..e88d257 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -535,7 +535,7 @@
         return result;
     }
 
-    private int getDefaultMargin(View c, boolean leading, boolean horizontal) {
+    private int getDefaultMargin(View c, boolean horizontal, boolean leading) {
         // In the absence of any other information, calculate a default gap such
         // that, in a grid of identical components, the heights and the vertical
         // gaps are in the proportion of the golden ratio.
@@ -544,12 +544,12 @@
         return (int) (c.getMeasuredHeight() / GOLDEN_RATIO / 2);
     }
 
-    private int getDefaultMargin(View c, boolean isAtEdge, boolean leading, boolean horizontal) {
+    private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
         // todo remove DEFAULT_CONTAINER_MARGIN. Use padding? Seek advice on Themes/Styles, etc.
-        return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, leading, horizontal);
+        return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, horizontal, leading);
     }
 
-    private int getDefaultMarginValue(View c, LayoutParams p, boolean leading, boolean horizontal) {
+    private int getDefaultMarginValue(View c, LayoutParams p, boolean horizontal, boolean leading) {
         if (!mUseDefaultMargins) {
             return 0;
         }
@@ -558,15 +558,19 @@
         Interval span = group.span;
         boolean isAtEdge = leading ? (span.min == 0) : (span.max == axis.getCount());
 
-        return getDefaultMargin(c, isAtEdge, leading, horizontal);
+        return getDefaultMargin(c, isAtEdge, horizontal, leading);
     }
 
-    private int getMargin(View view, boolean leading, boolean horizontal) {
+    private int getMargin(View view, boolean horizontal, boolean leading) {
         LayoutParams lp = getLayoutParams(view);
         int margin = horizontal ?
                 (leading ? lp.leftMargin : lp.rightMargin) :
                 (leading ? lp.topMargin : lp.bottomMargin);
-        return margin == UNDEFINED ? getDefaultMarginValue(view, lp, leading, horizontal) : margin;
+        return margin == UNDEFINED ? getDefaultMarginValue(view, lp, horizontal, leading) : margin;
+    }
+
+    private int getTotalMargin(View child, boolean horizontal) {
+        return getMargin(child, horizontal, true) + getMargin(child, horizontal, false);
     }
 
     private static int valueIfDefined(int value, int defaultValue) {
@@ -749,8 +753,8 @@
                 View c = getChildAt(i);
                 drawRectangle(canvas,
                         c.getLeft() - getMargin(c, true, true),
-                        c.getTop() - getMargin(c, true, false),
-                        c.getRight() + getMargin(c, false, true),
+                        c.getTop() - getMargin(c, false, true),
+                        c.getRight() + getMargin(c, true, false),
                         c.getBottom() + getMargin(c, false, false), paint);
             }
         }
@@ -794,17 +798,12 @@
         return c.getVisibility() == View.GONE;
     }
 
-    private void measureChildWithMargins(View child,
-            int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
-
+    private void measureChildWithMargins(View child, int widthMeasureSpec, int heightMeasureSpec) {
         LayoutParams lp = getLayoutParams(child);
-        int hMargins = getMargin(child, true, true) + getMargin(child, false, true);
-        int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
-                mPaddingLeft + mPaddingRight + hMargins, lp.width);
-        int vMargins = getMargin(child, true, false) + getMargin(child, false, false);
-        int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
-                mPaddingTop + mPaddingBottom + vMargins, lp.height);
-
+        int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+                mPaddingLeft + mPaddingRight + getTotalMargin(child, true), lp.width);
+        int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+                mPaddingTop + mPaddingBottom + getTotalMargin(child, false), lp.height);
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     }
 
@@ -842,9 +841,7 @@
     private int getMeasurementIncludingMargin(View c, boolean horizontal, int measurementType) {
         int result = getMeasurement(c, horizontal, measurementType);
         if (mAlignmentMode == ALIGN_MARGINS) {
-            int leadingMargin = getMargin(c, true, horizontal);
-            int trailingMargin = getMargin(c, false, horizontal);
-            return result + leadingMargin + trailingMargin;
+            return result + getTotalMargin(c, horizontal);
         }
         return result;
     }
@@ -919,8 +916,8 @@
 
             if (mAlignmentMode == ALIGN_MARGINS) {
                 int leftMargin = getMargin(c, true, true);
-                int topMargin = getMargin(c, true, false);
-                int rightMargin = getMargin(c, false, true);
+                int topMargin = getMargin(c, false, true);
+                int rightMargin = getMargin(c, true, false);
                 int bottomMargin = getMargin(c, false, false);
 
                 // Same calculation as getMeasurementIncludingMargin()
@@ -1387,7 +1384,7 @@
                 Group g = horizontal ? lp.columnGroup : lp.rowGroup;
                 Interval span = g.span;
                 int index = leading ? span.min : span.max;
-                margins[index] = max(margins[index], getMargin(c, leading, horizontal));
+                margins[index] = max(margins[index], getMargin(c, horizontal, leading));
             }
         }
 
@@ -1817,7 +1814,8 @@
         }
 
         private int getDefaultWeight(int size) {
-            return (size == MATCH_PARENT) ? DEFAULT_WEIGHT_1 : DEFAULT_WEIGHT_0;
+            //return (size == MATCH_PARENT) ? DEFAULT_WEIGHT_1 : DEFAULT_WEIGHT_0;
+            return DEFAULT_WEIGHT_0;
         }
 
         private void init(Context context, AttributeSet attrs, int defaultGravity) {
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index cbb110a..0c0205c 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -464,8 +464,7 @@
                 break;
             case MeasureSpec.EXACTLY:
             default:
-                // use the specified size, if non-zero
-                result = specSize != 0 ? specSize : desired;
+                result = specSize;
         }
         return result;
     }
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index dd68d82..03c6022 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -101,6 +101,10 @@
         android:visibility="gone"
         />
 
+    <!-- We need MATCH_PARENT here only to force the size of the parent to be passed to
+    the pattern view for it to compute its size. This is an unusual case, caused by
+    LockPatternView's requirement to maintain a square aspect ratio based on the width
+    of the screen. -->
     <com.android.internal.widget.LockPatternView
         android:id="@+id/lockPattern"
         android:layout_width="match_parent"
@@ -109,6 +113,8 @@
         android:layout_marginRight="8dip"
         android:layout_marginBottom="4dip"
         android:layout_marginLeft="8dip"
+        android:layout_gravity="center|bottom"
+        android:layout_rowWeight="1"
      />
 
     <TextView
@@ -123,8 +129,7 @@
     <!-- Footer: an emergency call button and an initially hidden "Forgot pattern" button -->
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_gravity="center">
+        android:layout_gravity="fill_horizontal">
 
         <Button android:id="@+id/emergencyCallButton"
             android:layout_width="wrap_content"
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index 2105deb..649b98a 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -38,6 +38,7 @@
 import android.graphics.Rect;
 import android.media.videoeditor.MediaImageItem;
 import android.media.videoeditor.MediaItem;
+import android.media.MediaMetadataRetriever;
 import android.util.Log;
 import android.util.Xml;
 import android.view.Surface;
@@ -1833,12 +1834,32 @@
             }
 
             Bitmap projectBitmap = null;
-            try {
-                projectBitmap = mI.getThumbnail(width, height, 500);
-            } catch (IllegalArgumentException e) {
-                throw new IllegalArgumentException ("Illegal argument error creating project thumbnail");
-            } catch (IOException e) {
-                throw new IllegalArgumentException ("IO Error creating project thumbnail");
+            String filename = mI.getFilename();
+            if (mI instanceof MediaVideoItem) {
+                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+                retriever.setDataSource(filename);
+                Bitmap bitmap = retriever.getFrameAtTime();
+                retriever.release();
+                retriever = null;
+                if (bitmap == null) {
+                    String msg = "Thumbnail extraction from " +
+                                    filename + " failed";
+                    throw new IllegalArgumentException(msg);
+                }
+                // Resize the thumbnail to the target size
+                projectBitmap =
+                    Bitmap.createScaledBitmap(bitmap, width, height, true);
+            } else {
+                try {
+                    projectBitmap = mI.getThumbnail(width, height, 500);
+                } catch (IllegalArgumentException e) {
+                    String msg = "Project thumbnail extraction from " +
+                                    filename + " failed";
+                    throw new IllegalArgumentException(msg);
+                } catch (IOException e) {
+                    String msg = "IO Error creating project thumbnail";
+                    throw new IllegalArgumentException(msg);
+                }
             }
 
             try {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index ea9911c..f075699d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -205,6 +205,8 @@
     // Duration is time scale based
     void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
     void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+
+    bool isTrackMalFormed() const;
     void sendTrackSummary(bool hasMultipleTracks);
 
     // Write the boxes
@@ -1975,7 +1977,6 @@
         }
 
         CHECK(timestampUs >= 0);
-
         LOGV("%s media time stamp: %lld and previous paused duration %lld",
                 mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
         if (timestampUs > mTrackDurationUs) {
@@ -2082,11 +2083,10 @@
 
     }
 
-    if (mSampleSizes.empty() ||                      // no samples written
-        (!mIsAudio && mNumStssTableEntries == 0) ||  // no sync frames for video
-        (OK != checkCodecSpecificData())) {          // no codec specific data
+    if (isTrackMalFormed()) {
         err = ERROR_MALFORMED;
     }
+
     mOwner->trackProgressStatus(mTrackId, -1, err);
 
     // Last chunk
@@ -2136,6 +2136,24 @@
     return err;
 }
 
+bool MPEG4Writer::Track::isTrackMalFormed() const {
+    if (mSampleSizes.empty()) {                      // no samples written
+        LOGE("The number of recorded samples is 0");
+        return true;
+    }
+
+    if (!mIsAudio && mNumStssTableEntries == 0) {  // no sync frames for video
+        LOGE("There are no sync frames for video track");
+        return true;
+    }
+
+    if (OK != checkCodecSpecificData()) {         // no codec specific data
+        return true;
+    }
+
+    return false;
+}
+
 void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
 
     // Send track summary only if test mode is enabled.
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
index 187a486..60906a1 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
@@ -1,93 +1,96 @@
-/*

- * Copyright (C) 2011 The Android Open Source Project

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *      http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-package com.android.systemui.usb;

-

-import android.app.Activity;

-import android.app.AlertDialog;

-import android.content.Context;

-import android.content.DialogInterface;

-import android.hardware.usb.UsbManager;

-import android.os.Bundle;

-import android.view.LayoutInflater;

-import android.view.View;

-import android.util.Log;

-import android.widget.Button;

-

-import java.io.File;

-

-import com.android.systemui.R;

-

-public class UsbPreferenceActivity extends Activity implements View.OnClickListener  {

-

-    private static final String TAG = "UsbPreferenceActivity";

-

-    private UsbManager mUsbManager;

-    private String mCurrentFunction;

-    private String[] mFunctions;

-    private String mInstallerImagePath;

-    private Button mMtpPtpButton;

-    private Button mInstallerCdButton;

-    private boolean mPtpActive;

-

-    @Override

-    public void onCreate(Bundle icicle) {

-        super.onCreate(icicle);

-

-        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);

-

-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);

-        dialogBuilder.setTitle(getString(R.string.usb_preference_title));

-

-        LayoutInflater inflater = (LayoutInflater)getSystemService(

-                Context.LAYOUT_INFLATER_SERVICE);

-        View buttonView = inflater.inflate(R.layout.usb_preference_buttons, null);

-        dialogBuilder.setView(buttonView);

-        mMtpPtpButton = (Button)buttonView.findViewById(R.id.mtp_ptp_button);

-        mInstallerCdButton = (Button)buttonView.findViewById(R.id.installer_cd_button);

-        mMtpPtpButton.setOnClickListener(this);

-        mInstallerCdButton.setOnClickListener(this);

-

-        mPtpActive = mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP);

-        if (mPtpActive) {

-            mMtpPtpButton.setText(R.string.use_mtp_button_title);

-        }

-

-        mInstallerImagePath = getString(com.android.internal.R.string.config_isoImagePath);

-        if (!(new File(mInstallerImagePath)).exists()) {

-            mInstallerCdButton.setVisibility(View.GONE);

-        }

-

-        dialogBuilder.show();

-    }

-

-    public void onClick(View v) {

-        if (v.equals(mMtpPtpButton)) {

-            if (mPtpActive) {

-                mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_MTP);

-                mUsbManager.setDefaultFunction(UsbManager.USB_FUNCTION_MTP);

-            } else {

-                mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_PTP);

-                mUsbManager.setDefaultFunction(UsbManager.USB_FUNCTION_PTP);

-            }

-        } else if (v.equals(mInstallerCdButton)) {

-            mUsbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_MASS_STORAGE);

-            mUsbManager.setMassStorageBackingFile(mInstallerImagePath);

-        }

-

+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.usb;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.util.Log;
+import android.widget.Button;
+
+import java.io.File;
+
+import com.android.systemui.R;
+
+public class UsbPreferenceActivity extends Activity implements View.OnClickListener  {
+
+    private static final String TAG = "UsbPreferenceActivity";
+
+    private UsbManager mUsbManager;
+    private String mCurrentFunction;
+    private String[] mFunctions;
+    private String mInstallerImagePath;
+    private AlertDialog mDialog;
+    private Button mMtpPtpButton;
+    private Button mInstallerCdButton;
+    private boolean mPtpActive;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
+
+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
+        dialogBuilder.setTitle(getString(R.string.usb_preference_title));
+
+        LayoutInflater inflater = (LayoutInflater)getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+        View buttonView = inflater.inflate(R.layout.usb_preference_buttons, null);
+        dialogBuilder.setView(buttonView);
+        mMtpPtpButton = (Button)buttonView.findViewById(R.id.mtp_ptp_button);
+        mInstallerCdButton = (Button)buttonView.findViewById(R.id.installer_cd_button);
+        mMtpPtpButton.setOnClickListener(this);
+        mInstallerCdButton.setOnClickListener(this);
+
+        mPtpActive = mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP);
+        if (mPtpActive) {
+            mMtpPtpButton.setText(R.string.use_mtp_button_title);
+        }
+
+        mInstallerImagePath = getString(com.android.internal.R.string.config_isoImagePath);
+        if (!(new File(mInstallerImagePath)).exists()) {
+            mInstallerCdButton.setVisibility(View.GONE);
+        }
+
+        mDialog = dialogBuilder.show();
+    }
+
+    public void onClick(View v) {
+        if (v.equals(mMtpPtpButton)) {
+            if (mPtpActive) {
+                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
+            } else {
+                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true);
+            }
+        } else if (v.equals(mInstallerCdButton)) {
+            // installer CD is never default
+            mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MASS_STORAGE, false);
+            mUsbManager.setMassStorageBackingFile(mInstallerImagePath);
+        }
+
+        if (mDialog != null) {
+            mDialog.dismiss();
+        }
         finish();

-    }

-}

+    }
+}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index a9dfb22..f6dd43a 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -32,6 +32,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Handler;
@@ -814,6 +815,8 @@
 
         final AtomicInteger mInteractionIdCounter = new AtomicInteger();
 
+        final Rect mTempBounds = new Rect();
+
         // the events pending events to be dispatched to this service
         final SparseArray<AccessibilityEvent> mPendingEvents =
             new SparseArray<AccessibilityEvent>();
@@ -932,9 +935,10 @@
                 AccessibilityNodeInfo info = mCallback.getFindAccessibilityNodeInfoResultAndClear(
                         interactionId);
                 if (info != null) {
+                    applyCompatibilityScaleIfNeeded(info);
                     info.setConnection(this);
+                    info.setSealed(true);
                 }
-                info.setSealed(true);
                 return info;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -979,6 +983,7 @@
                     final int infoCount = infos.size();
                     for (int i = 0; i < infoCount; i++) {
                         AccessibilityNodeInfo info = infos.get(i);
+                        applyCompatibilityScaleIfNeeded(info);
                         info.setConnection(this);
                         info.setSealed(true);
                     }
@@ -1019,6 +1024,7 @@
                 AccessibilityNodeInfo info =
                      mCallback.getFindAccessibilityNodeInfoResultAndClear(interactionId);
                 if (info != null) {
+                    applyCompatibilityScaleIfNeeded(info);
                     info.setConnection(this);
                     info.setSealed(true);
                 }
@@ -1093,6 +1099,24 @@
             }
             return mWindowIdToInteractionConnectionMap.get(windowId);
         }
+
+        private void applyCompatibilityScaleIfNeeded(AccessibilityNodeInfo info) {
+            IBinder windowToken = mWindowIdToWindowTokenMap.get(info.getWindowId());
+            final float scale = mWindowManagerService.getWindowCompatibilityScale(windowToken);
+
+            if (scale == 1.0f) {
+                return;
+            }
+
+            Rect bounds = mTempBounds;
+            info.getBoundsInParent(bounds);
+            bounds.scale(scale);
+            info.setBoundsInParent(bounds);
+
+            info.getBoundsInScreen(bounds);
+            bounds.scale(scale);
+            info.setBoundsInScreen(bounds);
+        }
     }
 
     final class SecurityPolicy {
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 15e67d0..946a270 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -509,9 +509,9 @@
         }
         try {
             if (enabled) {
-                usbManager.setPrimaryFunction(UsbManager.USB_FUNCTION_RNDIS);
+                usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
             } else {
-                usbManager.setPrimaryFunction(null);
+                usbManager.setCurrentFunction(null, false);
             }
         } catch (Exception e) {
             Log.e(TAG, "Error toggling usb RNDIS", e);
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index b7f9d5c..918f1b6 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -77,9 +77,8 @@
 
     private static final int MSG_UPDATE_STATE = 0;
     private static final int MSG_ENABLE_ADB = 1;
-    private static final int MSG_SET_PRIMARY_FUNCTION = 2;
-    private static final int MSG_SET_DEFAULT_FUNCTION = 3;
-    private static final int MSG_SYSTEM_READY = 4;
+    private static final int MSG_SET_CURRENT_FUNCTION = 2;
+    private static final int MSG_SYSTEM_READY = 3;
 
     // Delay for debouncing USB disconnects.
     // We often get rapid connect/disconnect events when enabling USB functions,
@@ -227,7 +226,7 @@
                 mHandler.updateState(state);
             } else if ("START".equals(accessory)) {
                 Slog.d(TAG, "got accessory start");
-                setPrimaryFunction(UsbManager.USB_FUNCTION_ACCESSORY);
+                setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false);
             }
         }
     };
@@ -371,6 +370,14 @@
             sendMessage(m);
         }
 
+        public void sendMessage(int what, Object arg0, boolean arg1) {
+            removeMessages(what);
+            Message m = Message.obtain(this, what);
+            m.obj = arg0;
+            m.arg1 = (arg1 ? 1 : 0);
+            sendMessage(m);
+        }
+
         public void updateState(String state) {
             int connected, configured;
 
@@ -395,24 +402,30 @@
             sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
         }
 
-        private boolean setUsbConfig(String config) {
-            // set the new configuration
-            SystemProperties.set("sys.usb.config", config);
+        private boolean waitForState(String state) {
             // wait for the transition to complete.
             // give up after 1 second.
             for (int i = 0; i < 20; i++) {
                 // State transition is done when sys.usb.conf.done is set to the new configuration
-                if (config.equals(SystemProperties.get("sys.usb.state"))) return true;
+                if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
                 try {
                     // try again in 50ms
                     Thread.sleep(50);
                 } catch (InterruptedException e) {
                 }
             }
+            Log.e(TAG, "waitForState(" + state + ") FAILED");
             return false;
         }
 
-        private void setCurrentFunctions(String functions) {
+        private boolean setUsbConfig(String config) {
+            Log.d(TAG, "setUsbConfig(" + config + ")");
+            // set the new configuration
+            SystemProperties.set("sys.usb.config", config);
+            return waitForState(config);
+        }
+
+        private void doSetCurrentFunctions(String functions) {
             if (!mCurrentFunctions.equals(functions)) {
                 if (!setUsbConfig("none") || !setUsbConfig(functions)) {
                     Log.e(TAG, "Failed to switch USB configuration to " + functions);
@@ -428,17 +441,14 @@
             if (enable != mAdbEnabled) {
                 mAdbEnabled = enable;
                 String functions;
+                // Due to the persist.sys.usb.config property trigger, changing adb state requires
+                // switching to default function
                 if (enable) {
-                    functions = addFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
-                    mDefaultFunctions = addFunction(mDefaultFunctions,
-                            UsbManager.USB_FUNCTION_ADB);
+                    functions = addFunction(mDefaultFunctions, UsbManager.USB_FUNCTION_ADB);
                 } else {
-                    functions = removeFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
-                    mDefaultFunctions = removeFunction(mDefaultFunctions,
-                            UsbManager.USB_FUNCTION_ADB);
+                    functions = removeFunction(mDefaultFunctions, UsbManager.USB_FUNCTION_ADB);
                 }
-                SystemProperties.set("persist.sys.usb.config", mDefaultFunctions);
-                setCurrentFunctions(functions);
+                setCurrentFunction(functions, true);
                 updateAdbNotification(mAdbEnabled && mConnected);
             }
         }
@@ -449,7 +459,7 @@
             } else {
                 functionList = removeFunction(functionList, UsbManager.USB_FUNCTION_ADB);
             }
-            setCurrentFunctions(functionList);
+            doSetCurrentFunctions(functionList);
         }
 
         private void updateCurrentAccessory() {
@@ -503,8 +513,6 @@
 
         @Override
         public void handleMessage(Message msg) {
-            String function;
-
             switch (msg.what) {
                 case MSG_UPDATE_STATE:
                     mConnected = (msg.arg1 == 1);
@@ -518,7 +526,7 @@
 
                     if (!mConnected) {
                         // restore defaults when USB is disconnected
-                        setCurrentFunctions(mDefaultFunctions);
+                        doSetCurrentFunctions(mDefaultFunctions);
                     }
                     if (mSystemReady) {
                         updateUsbState();
@@ -527,20 +535,31 @@
                 case MSG_ENABLE_ADB:
                     setAdbEnabled(msg.arg1 == 1);
                     break;
-                case MSG_SET_PRIMARY_FUNCTION:
-                    function = (String)msg.obj;
-                    if (function == null) {
-                        function = mDefaultFunctions;
+                case MSG_SET_CURRENT_FUNCTION:
+                    String function = (String)msg.obj;
+                    boolean makeDefault = (msg.arg1 == 1);
+                    if (makeDefault) {
+                        if (function == null) {
+                            throw new NullPointerException();
+                        }
+                        if (mAdbEnabled) {
+                            function = addFunction(function, UsbManager.USB_FUNCTION_ADB);
+                        }
+
+                        setUsbConfig("none");
+                        // setting this property will change the current USB state
+                        // via a property trigger
+                        SystemProperties.set("persist.sys.usb.config", function);
+                        if (waitForState(function)) {
+                            mCurrentFunctions = function;
+                            mDefaultFunctions = function;
+                        }
+                    } else {
+                        if (function == null) {
+                            function = mDefaultFunctions;
+                        }
+                        setEnabledFunctions(function);
                     }
-                    setEnabledFunctions(function);
-                    break;
-                case MSG_SET_DEFAULT_FUNCTION:
-                    function = (String)msg.obj;
-                    if (mAdbEnabled) {
-                        function = addFunction(function, UsbManager.USB_FUNCTION_ADB);
-                    }
-                    SystemProperties.set("persist.sys.usb.config", function);
-                    mDefaultFunctions = function;
                     break;
                 case MSG_SYSTEM_READY:
                     updateUsbNotification(mConnected);
@@ -588,15 +607,8 @@
             return nativeOpenAccessory();
         }
 
-    public void setPrimaryFunction(String function) {
-        mHandler.sendMessage(MSG_SET_PRIMARY_FUNCTION, function);
-    }
-
-    public void setDefaultFunction(String function) {
-        if (function == null) {
-            throw new NullPointerException();
-        }
-        mHandler.sendMessage(MSG_SET_DEFAULT_FUNCTION, function);
+    public void setCurrentFunction(String function, boolean makeDefault) {
+        mHandler.sendMessage(MSG_SET_CURRENT_FUNCTION, function, makeDefault);
     }
 
     public void setMassStorageBackingFile(String path) {
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 193638f..9f2c17a 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -146,19 +146,10 @@
         mSettingsManager.clearDefaults(packageName);
     }
 
-    public void setPrimaryFunction(String function) {
+    public void setCurrentFunction(String function, boolean makeDefault) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
         if (mDeviceManager != null) {
-            mDeviceManager.setPrimaryFunction(function);
-        } else {
-            throw new IllegalStateException("USB device mode not supported");
-        }
-    }
-
-    public void setDefaultFunction(String function) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-        if (mDeviceManager != null) {
-            mDeviceManager.setDefaultFunction(function);
+            mDeviceManager.setCurrentFunction(function, makeDefault);
         } else {
             throw new IllegalStateException("USB device mode not supported");
         }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 1c87f5b..dba170a 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2776,6 +2776,13 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    public float getWindowCompatibilityScale(IBinder windowToken) {
+        synchronized (mWindowMap) {
+            WindowState windowState = mWindowMap.get(windowToken);
+            return (windowState != null) ? windowState.mGlobalScale : 1.0f;
+        }
+    }
+
     private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
         if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
                 + (lp != null ? lp.packageName : null)