Merge "Add more sms error codes"
am: c16da498d5

Change-Id: Id19bb14ebea3b0124af3a5990613a15d8c2fa44c
diff --git a/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
index 34f6d7d..adbe9d0 100644
--- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.hardware.usb.IUsbManager;
-import android.hardware.usb.UsbManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
@@ -39,9 +38,6 @@
                 + "\n"
                 + "usage: svc usb setFunction [function] [usbDataUnlocked=false]\n"
                 + "         Set the current usb function and optionally the data lock state.\n\n"
-                + "       svc usb setScreenUnlockedFunctions [function]\n"
-                + "         Sets the functions which, if the device was charging,"
-                    + " become current on screen unlock.\n"
                 + "       svc usb getFunction\n"
                 + "          Gets the list of currently enabled functions\n";
     }
@@ -66,16 +62,6 @@
             } else if ("getFunction".equals(args[1])) {
                 System.err.println(SystemProperties.get("sys.usb.config"));
                 return;
-            } else if ("setScreenUnlockedFunctions".equals(args[1])) {
-                IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
-                        Context.USB_SERVICE));
-                try {
-                    usbMgr.setScreenUnlockedFunctions((args.length >= 3 ? args[2] :
-                            UsbManager.USB_FUNCTION_NONE));
-                } catch (RemoteException e) {
-                    System.err.println("Error communicating with UsbManager: " + e);
-                }
-                return;
             }
         }
         System.err.println(longHelp());
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index f2160e1..c8d9839 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -268,11 +268,4 @@
      * @param token The IApplicationToken for the activity
      */
     public abstract void setFocusedActivity(IBinder token);
-
-    public interface ScreenObserver {
-        public void onAwakeStateChanged(boolean isAwake);
-        public void onKeyguardStateChanged(boolean isShowing);
-    }
-
-    public abstract void registerScreenObserver(ScreenObserver observer);
 }
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 4e8c45d..025d46d 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -96,11 +96,6 @@
      */
     void setCurrentFunction(String function, boolean usbDataUnlocked);
 
-    /* Sets the screen unlocked USB function(s), which will be set automatically
-     * when the screen is unlocked.
-     */
-    void setScreenUnlockedFunctions(String function);
-
     /* Allow USB debugging from the attached host. If alwaysAllow is true, add the
      * the public key to list of host keys that the user has approved.
      */
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 48e8d34..d73d3d8 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -590,32 +590,6 @@
     }
 
     /**
-     * Sets the screen unlocked functions, which are persisted and set as the current functions
-     * whenever the screen is unlocked.
-     * <p>
-     * The allowed values are: {@link #USB_FUNCTION_NONE},
-     * {@link #USB_FUNCTION_MIDI}, {@link #USB_FUNCTION_MTP}, {@link #USB_FUNCTION_PTP},
-     * or {@link #USB_FUNCTION_RNDIS}.
-     * {@link #USB_FUNCTION_NONE} has the effect of switching off this feature, so functions
-     * no longer change on screen unlock.
-     * </p><p>
-     * Note: When the screen is on, this method will apply given functions as current functions,
-     * which is asynchronous and may fail silently without applying the requested changes.
-     * </p>
-     *
-     * @param function function to set as default
-     *
-     * {@hide}
-     */
-    public void setScreenUnlockedFunctions(String function) {
-        try {
-            mService.setScreenUnlockedFunctions(function);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Returns a list of physical USB ports on the device.
      * <p>
      * This list is guaranteed to contain all dual-role USB Type C ports but it might
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index c94ae93..bc4d955 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -21,6 +21,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.BitUtils;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6c7455d..91e2f7d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3866,7 +3866,6 @@
     private void onTouchDown(MotionEvent ev) {
         mHasPerformedLongPress = false;
         mActivePointerId = ev.getPointerId(0);
-        hideSelector();
 
         if (mTouchMode == TOUCH_MODE_OVERFLING) {
             // Stopped the fling. It is a scroll.
@@ -5227,21 +5226,17 @@
         }
 
         mRecycler.fullyDetachScrapViews();
-        boolean selectorOnScreen = false;
         if (!inTouchMode && mSelectedPosition != INVALID_POSITION) {
             final int childIndex = mSelectedPosition - mFirstPosition;
             if (childIndex >= 0 && childIndex < getChildCount()) {
                 positionSelector(mSelectedPosition, getChildAt(childIndex));
-                selectorOnScreen = true;
             }
         } else if (mSelectorPosition != INVALID_POSITION) {
             final int childIndex = mSelectorPosition - mFirstPosition;
             if (childIndex >= 0 && childIndex < getChildCount()) {
-                positionSelector(mSelectorPosition, getChildAt(childIndex));
-                selectorOnScreen = true;
+                positionSelector(INVALID_POSITION, getChildAt(childIndex));
             }
-        }
-        if (!selectorOnScreen) {
+        } else {
             mSelectorRect.setEmpty();
         }
 
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 324f923..6af41a5 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -256,7 +256,7 @@
             final int hgrav = Gravity.getAbsoluteGravity(mDropDownGravity,
                     mAnchorView.getLayoutDirection()) & Gravity.HORIZONTAL_GRAVITY_MASK;
             if (hgrav == Gravity.RIGHT) {
-                xOffset -= mAnchorView.getWidth();
+                xOffset += mAnchorView.getWidth();
             }
 
             popup.setHorizontalOffset(xOffset);
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 445379b..d9ca5be 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -263,6 +263,7 @@
                     mShownAnchorView, mOverflowOnly, mPopupStyleAttr, mPopupStyleRes);
             subPopup.setPresenterCallback(mPresenterCallback);
             subPopup.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(subMenu));
+            subPopup.setGravity(mDropDownGravity);
 
             // Pass responsibility for handling onDismiss to the submenu.
             subPopup.setOnDismissListener(mOnDismissListener);
@@ -272,17 +273,8 @@
             mMenu.close(false /* closeAllMenus */);
 
             // Show the new sub-menu popup at the same location as this popup.
-            int horizontalOffset = mPopup.getHorizontalOffset();
+            final int horizontalOffset = mPopup.getHorizontalOffset();
             final int verticalOffset = mPopup.getVerticalOffset();
-
-            // As xOffset of parent menu popup is subtracted with Anchor width for Gravity.RIGHT,
-            // So, again to display sub-menu popup in same xOffset, add the Anchor width.
-            final int hgrav = Gravity.getAbsoluteGravity(mDropDownGravity,
-                mAnchorView.getLayoutDirection()) & Gravity.HORIZONTAL_GRAVITY_MASK;
-            if (hgrav == Gravity.RIGHT) {
-              horizontalOffset += mAnchorView.getWidth();
-            }
-
             if (subPopup.tryShow(horizontalOffset, verticalOffset)) {
                 if (mPresenterCallback != null) {
                     mPresenterCallback.onOpenSubMenu(subMenu);
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index c0a8acd..ab9912a 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1041,13 +1041,6 @@
             </intent-filter>
         </activity>
 
-        <activity android:name="android.view.menu.ContextMenuActivity" android:label="ContextMenu" android:theme="@android:style/Theme.Material">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
         <activity android:name="android.view.menu.MenuWith1Item" android:label="MenuWith1Item">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/core/tests/coretests/res/layout/context_menu.xml b/core/tests/coretests/res/layout/context_menu.xml
deleted file mode 100644
index 3b9e2bd..0000000
--- a/core/tests/coretests/res/layout/context_menu.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2018, 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.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-    <LinearLayout
-            android:id="@+id/context_menu_target_ltr"
-            android:orientation="horizontal"
-            android:layoutDirection="ltr"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="50px"
-            android:layout_marginEnd="50px">
-        <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="LTR"/>
-    </LinearLayout>
-
-    <LinearLayout
-            android:id="@+id/context_menu_target_rtl"
-            android:orientation="horizontal"
-            android:layoutDirection="rtl"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="50px"
-            android:layout_marginEnd="50px">
-        <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="RTL"/>
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/core/tests/coretests/src/android/util/PollingCheck.java b/core/tests/coretests/src/android/util/PollingCheck.java
deleted file mode 100644
index 468b9b2..0000000
--- a/core/tests/coretests/src/android/util/PollingCheck.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import org.junit.Assert;
-
-/**
- * Utility used for testing that allows to poll for a certain condition to happen within a timeout.
- *
- * Code copied from com.android.compatibility.common.util.PollingCheck
- */
-public abstract class PollingCheck {
-
-    private static final long DEFAULT_TIMEOUT = 3000;
-    private static final long TIME_SLICE = 50;
-    private final long mTimeout;
-
-    /**
-     * The condition that the PollingCheck should use to proceed successfully.
-     */
-    public interface PollingCheckCondition {
-
-        /**
-         * @return Whether the polling condition has been met.
-         */
-        boolean canProceed();
-    }
-
-    public PollingCheck(long timeout) {
-        mTimeout = timeout;
-    }
-
-    protected abstract boolean check();
-
-    /**
-     * Start running the polling check.
-     */
-    public void run() {
-        if (check()) {
-            return;
-        }
-
-        long timeout = mTimeout;
-        while (timeout > 0) {
-            try {
-                Thread.sleep(TIME_SLICE);
-            } catch (InterruptedException e) {
-                Assert.fail("unexpected InterruptedException");
-            }
-
-            if (check()) {
-                return;
-            }
-
-            timeout -= TIME_SLICE;
-        }
-
-        Assert.fail("unexpected timeout");
-    }
-
-    /**
-     * Instantiate and start polling for a given condition with a default 3000ms timeout.
-     *
-     * @param condition The condition to check for success.
-     */
-    public static void waitFor(final PollingCheckCondition condition) {
-        new PollingCheck(DEFAULT_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return condition.canProceed();
-            }
-        }.run();
-    }
-
-    /**
-     * Instantiate and start polling for a given condition.
-     *
-     * @param timeout Time out in ms
-     * @param condition The condition to check for success.
-     */
-    public static void waitFor(long timeout, final PollingCheckCondition condition) {
-        new PollingCheck(timeout) {
-            @Override
-            protected boolean check() {
-                return condition.canProceed();
-            }
-        }.run();
-    }
-}
-
diff --git a/core/tests/coretests/src/android/view/menu/ContextMenuActivity.java b/core/tests/coretests/src/android/view/menu/ContextMenuActivity.java
deleted file mode 100644
index 830b3d5..0000000
--- a/core/tests/coretests/src/android/view/menu/ContextMenuActivity.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.menu;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View;
-
-import com.android.frameworks.coretests.R;
-
-public class ContextMenuActivity extends Activity {
-
-    static final String LABEL_ITEM = "Item";
-    static final String LABEL_SUBMENU = "Submenu";
-    static final String LABEL_SUBITEM = "Subitem";
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.context_menu);
-        registerForContextMenu(getTargetLtr());
-        registerForContextMenu(getTargetRtl());
-    }
-
-    @Override
-    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
-        menu.add(LABEL_ITEM);
-        menu.addSubMenu(LABEL_SUBMENU).add(LABEL_SUBITEM);
-    }
-
-    View getTargetLtr() {
-        return findViewById(R.id.context_menu_target_ltr);
-    }
-
-    View getTargetRtl() {
-        return findViewById(R.id.context_menu_target_rtl);
-    }
-}
diff --git a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java
deleted file mode 100644
index 59d4e55..0000000
--- a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.menu;
-
-import android.content.Context;
-import android.graphics.Point;
-import android.support.test.filters.MediumTest;
-import android.test.ActivityInstrumentationTestCase;
-import android.util.PollingCheck;
-import android.view.Display;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.espresso.ContextMenuUtils;
-
-@MediumTest
-public class ContextMenuTest extends ActivityInstrumentationTestCase<ContextMenuActivity> {
-
-    public ContextMenuTest() {
-        super("com.android.frameworks.coretests", ContextMenuActivity.class);
-    }
-
-    public void testContextMenuPositionLtr() throws InterruptedException {
-        testMenuPosition(getActivity().getTargetLtr());
-    }
-
-    public void testContextMenuPositionRtl() throws InterruptedException {
-        testMenuPosition(getActivity().getTargetRtl());
-    }
-
-    private void testMenuPosition(View target) throws InterruptedException {
-        final int minScreenDimension = getMinScreenDimension();
-        if (minScreenDimension < 320) {
-            // Assume there is insufficient room for the context menu to be aligned properly.
-            return;
-        }
-
-        int offsetX = target.getWidth() / 2;
-        int offsetY = target.getHeight() / 2;
-
-        getInstrumentation().runOnMainSync(() -> target.performLongClick(offsetX, offsetY));
-
-        PollingCheck.waitFor(
-                () -> ContextMenuUtils.isMenuItemClickable(ContextMenuActivity.LABEL_SUBMENU));
-
-        ContextMenuUtils.assertContextMenuAlignment(target, offsetX, offsetY);
-
-        ContextMenuUtils.clickMenuItem(ContextMenuActivity.LABEL_SUBMENU);
-
-        PollingCheck.waitFor(
-                () -> ContextMenuUtils.isMenuItemClickable(ContextMenuActivity.LABEL_SUBITEM));
-
-        if (minScreenDimension < getCascadingMenuTreshold()) {
-            // A non-cascading submenu should be displayed at the same location as its parent.
-            // Not testing cascading submenu position, as it is positioned differently.
-            ContextMenuUtils.assertContextMenuAlignment(target, offsetX, offsetY);
-        }
-    }
-
-    /**
-     * Returns the minimum of the default display's width and height.
-     */
-    private int getMinScreenDimension() {
-        final WindowManager windowManager = (WindowManager) getActivity().getSystemService(
-                Context.WINDOW_SERVICE);
-        final Display display = windowManager.getDefaultDisplay();
-        final Point displaySize = new Point();
-        display.getRealSize(displaySize);
-        return Math.min(displaySize.x, displaySize.y);
-    }
-
-    /**
-     * Returns the minimum display size where cascading submenus are supported.
-     */
-    private int getCascadingMenuTreshold() {
-        // Use the same dimension resource as in MenuPopupHelper.createPopup().
-        return getActivity().getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.cascading_menus_min_smallest_width);
-    }
-}
diff --git a/core/tests/coretests/src/android/widget/espresso/ContextMenuUtils.java b/core/tests/coretests/src/android/widget/espresso/ContextMenuUtils.java
index 487a881..c8218aa 100644
--- a/core/tests/coretests/src/android/widget/espresso/ContextMenuUtils.java
+++ b/core/tests/coretests/src/android/widget/espresso/ContextMenuUtils.java
@@ -17,32 +17,25 @@
 package android.widget.espresso;
 
 import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
 import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
 import static android.support.test.espresso.matcher.ViewMatchers.hasFocus;
 import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
 import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
 import static android.support.test.espresso.matcher.ViewMatchers.withText;
 import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.not;
 
+import com.android.internal.view.menu.ListMenuItemView;
+
 import android.support.test.espresso.NoMatchingRootException;
 import android.support.test.espresso.NoMatchingViewException;
 import android.support.test.espresso.ViewInteraction;
 import android.support.test.espresso.matcher.ViewMatchers;
-import android.view.View;
 import android.widget.MenuPopupWindow.MenuDropDownListView;
 
-import com.android.internal.view.menu.ListMenuItemView;
-
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
-
 /**
  * Espresso utility methods for the context menu.
  */
@@ -89,15 +82,10 @@
     private static void asssertContextMenuContainsItemWithEnabledState(String itemLabel,
             boolean enabled) {
         onContextMenu().check(matches(
-                hasDescendant(getVisibleMenuItemMatcher(itemLabel, enabled))));
-    }
-
-    private static Matcher<View> getVisibleMenuItemMatcher(String itemLabel, boolean enabled) {
-        return allOf(
-                isAssignableFrom(ListMenuItemView.class),
-                hasDescendant(withText(itemLabel)),
-                enabled ? isEnabled() : not(isEnabled()),
-                isDisplayingAtLeast(90));
+                hasDescendant(allOf(
+                        isAssignableFrom(ListMenuItemView.class),
+                        enabled ? isEnabled() : not(isEnabled()),
+                        hasDescendant(withText(itemLabel))))));
     }
 
     /**
@@ -119,70 +107,4 @@
     public static void assertContextMenuContainsItemDisabled(String itemLabel) {
         asssertContextMenuContainsItemWithEnabledState(itemLabel, false);
     }
-
-    /**
-     * Asserts that the context menu window is aligned to a given view with a given offset.
-     *
-     * @param anchor Anchor view.
-     * @param offsetX x offset
-     * @param offsetY y offset.
-     * @throws AssertionError if the assertion fails
-     */
-    public static void assertContextMenuAlignment(View anchor, int offsetX, int offsetY) {
-        int [] expectedLocation = new int[2];
-        anchor.getLocationOnScreen(expectedLocation);
-        expectedLocation[0] += offsetX;
-        expectedLocation[1] += offsetY;
-
-        final boolean rtl = anchor.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
-
-        onContextMenu().check(matches(new TypeSafeMatcher<View>() {
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("root view ");
-                description.appendText(rtl ? "right" : "left");
-                description.appendText("=");
-                description.appendText(Integer.toString(offsetX));
-                description.appendText(", top=");
-                description.appendText(Integer.toString(offsetY));
-            }
-
-            @Override
-            public boolean matchesSafely(View view) {
-                View rootView = view.getRootView();
-                int [] actualLocation = new int[2];
-                rootView.getLocationOnScreen(actualLocation);
-                if (rtl) {
-                    actualLocation[0] += rootView.getWidth();
-                }
-                return expectedLocation[0] == actualLocation[0]
-                    && expectedLocation[1] == actualLocation[1];
-            }
-        }));
-    }
-
-    /**
-     * Check is the menu item is clickable (i.e. visible and enabled).
-     *
-     * @param itemLabel Label of the item.
-     * @return True if the menu item is clickable.
-     */
-    public static boolean isMenuItemClickable(String itemLabel) {
-        try {
-            onContextMenu().check(matches(
-                    hasDescendant(getVisibleMenuItemMatcher(itemLabel, true))));
-            return true;
-        } catch (NoMatchingRootException | NoMatchingViewException | AssertionError e) {
-            return false;
-        }
-    }
-
-    /**
-     * Click on a menu item with the specified label
-     * @param itemLabel Label of the item.
-     */
-    public static void clickMenuItem(String itemLabel) {
-        onView(getVisibleMenuItemMatcher(itemLabel, true))
-                .inRoot(withDecorView(hasFocus())).perform(click());
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 13617f1..533771a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -265,9 +265,7 @@
         mStatusBarIconController.getTransitionsController().dump(fd, pw, args);
         pw.println();
         pw.println(" NavigationBarTransitionsController:");
-        if (mNavigationBarController != null) {
-            mNavigationBarController.dump(fd, pw, args);
-        }
+        mNavigationBarController.dump(fd, pw, args);
         pw.println();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index e467903..b08b26d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -49,6 +49,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.qs.tiles.DndTile;
@@ -339,15 +340,11 @@
 
     private boolean shouldShowUI(int flags) {
         updateStatusBar();
-        // if status bar isn't null, check if phone is in AOD, else check flags
-        // since we could be using a different status bar
-        return mStatusBar != null ?
-                mStatusBar.getWakefulnessState() != WakefulnessLifecycle.WAKEFULNESS_ASLEEP
-                && mStatusBar.getWakefulnessState() !=
-                        WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP
+        return mStatusBar != null
+                && mStatusBar.getWakefulnessState() != WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+                && mStatusBar.getWakefulnessState() != WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP
                 && mStatusBar.isDeviceInteractive()
-                && (flags & AudioManager.FLAG_SHOW_UI) != 0
-                : (flags & AudioManager.FLAG_SHOW_UI) != 0;
+                && (flags & AudioManager.FLAG_SHOW_UI) != 0;
     }
 
     boolean onVolumeChangedW(int stream, int flags) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6c60b74..1740ab5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -201,7 +201,6 @@
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityManager.TaskThumbnailInfo;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityManagerInternal.ScreenObserver;
 import android.app.ActivityManagerInternal.SleepToken;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
@@ -1562,8 +1561,6 @@
         }
     }
 
-    final List<ScreenObserver> mScreenObservers = new ArrayList<>();
-
     final RemoteCallbackList<IProcessObserver> mProcessObservers = new RemoteCallbackList<>();
     ProcessChangeItem[] mActiveProcessChanges = new ProcessChangeItem[5];
 
@@ -1705,8 +1702,6 @@
     static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
     static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
     static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
-    static final int DISPATCH_SCREEN_AWAKE_MSG = 71;
-    static final int DISPATCH_SCREEN_KEYGUARD_MSG = 72;
     static final int START_USER_SWITCH_FG_MSG = 712;
     static final int NOTIFY_VR_KEYGUARD_MSG = 74;
 
@@ -2433,17 +2428,11 @@
                     }
                 }
             } break;
-            case DISPATCH_SCREEN_AWAKE_MSG: {
-                final boolean isAwake = msg.arg1 != 0;
-                for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
-                    mScreenObservers.get(i).onAwakeStateChanged(isAwake);
-                }
+            case NOTIFY_VR_SLEEPING_MSG: {
+                notifyVrManagerOfSleepState(msg.arg1 != 0);
             } break;
-            case DISPATCH_SCREEN_KEYGUARD_MSG: {
-                final boolean isShowing = msg.arg1 != 0;
-                for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
-                    mScreenObservers.get(i).onKeyguardStateChanged(isShowing);
-                }
+            case NOTIFY_VR_KEYGUARD_MSG: {
+                notifyVrManagerOfKeyguardState(msg.arg1 != 0);
             } break;
             case HANDLE_TRUST_STORAGE_UPDATE_MSG: {
                 synchronized (ActivityManagerService.this) {
@@ -3326,6 +3315,32 @@
                 mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
     }
 
+    private void sendNotifyVrManagerOfSleepState(boolean isSleeping) {
+        mHandler.sendMessage(
+                mHandler.obtainMessage(NOTIFY_VR_SLEEPING_MSG, isSleeping ? 1 : 0, 0));
+    }
+
+    private void notifyVrManagerOfSleepState(boolean isSleeping) {
+        final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
+        if (vrService == null) {
+            return;
+        }
+        vrService.onSleepStateChanged(isSleeping);
+    }
+
+    private void sendNotifyVrManagerOfKeyguardState(boolean isShowing) {
+        mHandler.sendMessage(
+                mHandler.obtainMessage(NOTIFY_VR_KEYGUARD_MSG, isShowing ? 1 : 0, 0));
+    }
+
+    private void notifyVrManagerOfKeyguardState(boolean isShowing) {
+        final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
+        if (vrService == null) {
+            return;
+        }
+        vrService.onKeyguardStateChanged(isShowing);
+    }
+
     final void showAskCompatModeDialogLocked(ActivityRecord r) {
         Message msg = Message.obtain();
         msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
@@ -12584,8 +12599,7 @@
             if (wasAwake != isAwake) {
                 // Also update state in a special way for running foreground services UI.
                 mServices.updateScreenStateLocked(isAwake);
-                mHandler.obtainMessage(DISPATCH_SCREEN_AWAKE_MSG, isAwake ? 1 : 0, 0)
-                        .sendToTarget();
+                sendNotifyVrManagerOfSleepState(!isAwake);
             }
         }
     }
@@ -12738,9 +12752,7 @@
                 Binder.restoreCallingIdentity(ident);
             }
         }
-
-        mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, showing ? 1 : 0, 0)
-                .sendToTarget();
+        sendNotifyVrManagerOfKeyguardState(showing);
     }
 
     @Override
@@ -24400,11 +24412,6 @@
                 }
             }
         }
-
-        @Override
-        public void registerScreenObserver(ScreenObserver observer) {
-            mScreenObservers.add(observer);
-        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 35b6ad3..7b1e12e 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -59,6 +59,13 @@
             int userId, int processId, @NonNull ComponentName calling);
 
     /**
+     * Set whether the system has acquired a sleep token.
+     *
+     * @param isAsleep is {@code true} if the device is asleep, or {@code false} otherwise.
+     */
+    public abstract void onSleepStateChanged(boolean isAsleep);
+
+    /**
      * Set whether the display used for VR output is on.
      *
      * @param isScreenOn is {@code true} if the display is on and can receive commands,
@@ -67,6 +74,13 @@
     public abstract void onScreenStateChanged(boolean isScreenOn);
 
     /**
+     * Set whether the keyguard is currently active/showing.
+     *
+     * @param isShowing is {@code true} if the keyguard is active/showing.
+     */
+    public abstract void onKeyguardStateChanged(boolean isShowing);
+
+    /**
      * Return NO_ERROR if the given package is installed on the device and enabled as a
      * VrListenerService for the given current user, or a negative error code indicating a failure.
      *
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 56cacf4..b0fd248 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -19,7 +19,6 @@
 
 import android.Manifest;
 import android.app.ActivityManagerInternal;
-import android.app.ActivityManagerInternal.ScreenObserver;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.INotificationManager;
@@ -105,8 +104,7 @@
  *
  * @hide
  */
-public class VrManagerService extends SystemService
-        implements EnabledComponentChangeListener, ScreenObserver {
+public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
 
     public static final String TAG = "VrManagerService";
     static final boolean DBG = false;
@@ -233,17 +231,15 @@
         }
     }
 
+    private void setSleepState(boolean isAsleep) {
+        setSystemState(FLAG_AWAKE, !isAsleep);
+    }
+
     private void setScreenOn(boolean isScreenOn) {
         setSystemState(FLAG_SCREEN_ON, isScreenOn);
     }
 
-    @Override
-    public void onAwakeStateChanged(boolean isAwake) {
-        setSystemState(FLAG_AWAKE, isAwake);
-    }
-
-    @Override
-    public void onKeyguardStateChanged(boolean isShowing) {
+    private void setKeyguardShowing(boolean isShowing) {
         setSystemState(FLAG_KEYGUARD_UNLOCKED, !isShowing);
     }
 
@@ -679,11 +675,21 @@
         }
 
         @Override
+        public void onSleepStateChanged(boolean isAsleep) {
+            VrManagerService.this.setSleepState(isAsleep);
+        }
+
+        @Override
         public void onScreenStateChanged(boolean isScreenOn) {
             VrManagerService.this.setScreenOn(isScreenOn);
         }
 
         @Override
+        public void onKeyguardStateChanged(boolean isShowing) {
+            VrManagerService.this.setKeyguardShowing(isShowing);
+        }
+
+        @Override
         public boolean isCurrentVrListener(String packageName, int userId) {
             return VrManagerService.this.isCurrentVrListener(packageName, userId);
         }
@@ -734,9 +740,6 @@
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
-            LocalServices.getService(ActivityManagerInternal.class)
-                    .registerScreenObserver(this);
-
             mNotificationManager = INotificationManager.Stub.asInterface(
                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
             synchronized (mLock) {
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index feb7b76..0cd9ac3 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -10,6 +10,5 @@
     static_libs: [
         "android.hardware.usb-V1.0-java",
         "android.hardware.usb-V1.1-java",
-        "android.hardware.usb.gadget-V1.0-java",
     ],
 }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index e3e5e3e..1b057f9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -16,9 +16,6 @@
 
 package com.android.server.usb;
 
-import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
-import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
@@ -29,7 +26,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -41,21 +37,12 @@
 import android.hardware.usb.UsbManager;
 import android.hardware.usb.UsbPort;
 import android.hardware.usb.UsbPortStatus;
-import android.hardware.usb.gadget.V1_0.GadgetFunction;
-import android.hardware.usb.gadget.V1_0.IUsbGadget;
-import android.hardware.usb.gadget.V1_0.IUsbGadgetCallback;
-import android.hardware.usb.gadget.V1_0.Status;
-import android.hidl.manager.V1_0.IServiceManager;
-import android.hidl.manager.V1_0.IServiceNotification;
 import android.os.BatteryManager;
-import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
-import android.os.HwBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UEventObserver;
@@ -73,7 +60,6 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.FgThread;
-import com.android.server.LocalServices;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -83,24 +69,32 @@
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
-import java.util.NoSuchElementException;
 import java.util.Scanner;
 import java.util.Set;
-import java.util.StringJoiner;
 
 /**
  * UsbDeviceManager manages USB state in device mode.
  */
-public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver {
+public class UsbDeviceManager {
 
     private static final String TAG = "UsbDeviceManager";
     private static final boolean DEBUG = false;
 
     /**
-     * The SharedPreference setting per user that stores the screen unlocked functions between
-     * sessions.
+     * The persistent property which stores whether adb is enabled or not.
+     * May also contain vendor-specific default functions for testing purposes.
      */
-    private static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";
+    private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
+
+    /**
+     * The non-persistent property which stores the current USB settings.
+     */
+    private static final String USB_CONFIG_PROPERTY = "sys.usb.config";
+
+    /**
+     * The non-persistent property which stores the current USB actual state.
+     */
+    private static final String USB_STATE_PROPERTY = "sys.usb.state";
 
     /**
      * ro.bootmode value when phone boots into usual Android.
@@ -134,12 +128,6 @@
     private static final int MSG_UPDATE_CHARGING_STATE = 9;
     private static final int MSG_UPDATE_HOST_STATE = 10;
     private static final int MSG_LOCALE_CHANGED = 11;
-    private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12;
-    private static final int MSG_UPDATE_SCREEN_LOCK = 13;
-    private static final int MSG_SET_CHARGING_FUNCTIONS = 14;
-    private static final int MSG_SET_FUNCTIONS_TIMEOUT = 15;
-    private static final int MSG_GET_CURRENT_USB_FUNCTIONS = 16;
-    private static final int MSG_FUNCTION_SWITCH_TIMEOUT = 17;
 
     private static final int AUDIO_MODE_SOURCE = 1;
 
@@ -155,9 +143,9 @@
     private static final String BOOT_MODE_PROPERTY = "ro.bootmode";
 
     private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";
+
     private UsbHandler mHandler;
     private boolean mBootCompleted;
-    private boolean mSystemReady;
 
     private final Object mLock = new Object();
 
@@ -173,6 +161,7 @@
     private boolean mMidiEnabled;
     private int mMidiCard;
     private int mMidiDevice;
+    private HashMap<String, HashMap<String, Pair<String, String>>> mOemModeMap;
     private String[] mAccessoryStrings;
     private UsbDebuggingManager mDebuggingManager;
     private final UsbAlsaManager mUsbAlsaManager;
@@ -180,7 +169,6 @@
     private Intent mBroadcastedIntent;
     private boolean mPendingBootBroadcast;
     private static Set<Integer> sBlackListedInterfaces;
-    private SharedPreferences mSettings;
 
     static {
         sBlackListedInterfaces = new HashSet<>();
@@ -229,31 +217,6 @@
         }
     };
 
-    @Override
-    public void onKeyguardStateChanged(boolean isShowing) {
-        int userHandle = ActivityManager.getCurrentUser();
-        boolean secure = mContext.getSystemService(KeyguardManager.class)
-                .isDeviceSecure(userHandle);
-        boolean unlocking = mContext.getSystemService(UserManager.class)
-                .isUserUnlockingOrUnlocked(userHandle);
-        if (DEBUG) {
-            Slog.v(TAG, "onKeyguardStateChanged: isShowing:" + isShowing + " secure:" + secure
-                    + " unlocking:" + unlocking + " user:" + userHandle);
-        }
-        // We are unlocked when the keyguard is down or non-secure, and user storage is unlocked.
-        mHandler.sendMessage(MSG_UPDATE_SCREEN_LOCK, (isShowing && secure) || !unlocking);
-    }
-
-    @Override
-    public void onAwakeStateChanged(boolean isAwake) {
-        // ignore
-    }
-
-    /** Called when a user is unlocked. */
-    public void onUnlockUser(int userHandle) {
-        onKeyguardStateChanged(false);
-    }
-
     public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
             UsbSettingsManager settingsManager) {
         mContext = context;
@@ -264,27 +227,9 @@
         mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
         initRndisAddress();
 
-        boolean halNotPresent = false;
-        try {
-            IUsbGadget.getService(true);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "USB GADGET HAL present but exception thrown", e);
-        } catch (NoSuchElementException e) {
-            halNotPresent = true;
-            Slog.i(TAG, "USB GADGET HAL not present in the device", e);
-        }
+        readOemUsbOverrideConfig();
 
-        if (halNotPresent) {
-            /**
-             * Initialze the legacy UsbHandler
-             */
-            mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext);
-        } else {
-            /**
-             * Initialize HAL based UsbHandler
-             */
-            mHandler = new UsbHandlerHal(FgThread.get().getLooper());
-        }
+        mHandler = new UsbHandler(FgThread.get().getLooper());
 
         if (nativeIsStartRequested()) {
             if (DEBUG) Slog.d(TAG, "accessory attached at boot");
@@ -358,8 +303,6 @@
     public void systemReady() {
         if (DEBUG) Slog.d(TAG, "systemReady");
 
-        LocalServices.getService(ActivityManagerInternal.class).registerScreenObserver(this);
-
         mNotificationManager = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
@@ -382,6 +325,15 @@
         massStorageSupported = primary != null && primary.allowMassStorage();
         mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_usbChargingMessage);
+
+        // make sure the ADB_ENABLED setting value matches the current state
+        try {
+            Settings.Global.putInt(mContentResolver,
+                    Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+        } catch (SecurityException e) {
+            // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed.
+            Slog.d(TAG, "ADB_ENABLED is restricted.");
+        }
         mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
     }
 
@@ -455,15 +407,7 @@
         return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
     }
 
-    private SharedPreferences getPinnedSharedPrefs(Context context) {
-        final File prefsFile = new File(new File(
-                Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
-                        context.getUserId(), context.getPackageName()), "shared_prefs"),
-                UsbDeviceManager.class.getSimpleName() + ".xml");
-        return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
-    }
-
-    private abstract class UsbHandler extends Handler {
+    private final class UsbHandler extends Handler {
 
         // current USB state
         private boolean mConnected;
@@ -471,53 +415,73 @@
         private boolean mSourcePower;
         private boolean mSinkPower;
         private boolean mConfigured;
-        protected boolean mUsbDataUnlocked;
+        private boolean mUsbDataUnlocked;
         private boolean mAudioAccessoryConnected;
         private boolean mAudioAccessorySupported;
-        protected String mCurrentFunctions;
-        protected boolean mCurrentFunctionsApplied;
+        private String mCurrentFunctions;
+        private boolean mCurrentFunctionsApplied;
         private UsbAccessory mCurrentAccessory;
         private int mUsbNotificationId;
         private boolean mAdbNotificationShown;
-        private int mCurrentUser;
+        private int mCurrentUser = UserHandle.USER_NULL;
         private boolean mUsbCharging;
+        private String mCurrentOemFunctions;
         private boolean mHideUsbNotification;
         private boolean mSupportsAllCombinations;
-        private String mScreenUnlockedFunctions = UsbManager.USB_FUNCTION_NONE;
-        private boolean mScreenLocked;
-        protected boolean mCurrentUsbFunctionsRequested;
-        protected boolean mCurrentUsbFunctionsReceived;
-
-        /**
-         * The persistent property which stores whether adb is enabled or not.
-         * May also contain vendor-specific default functions for testing purposes.
-         */
-        protected static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
 
         public UsbHandler(Looper looper) {
             super(looper);
+            try {
+                // Restore default functions.
 
-            mCurrentUser = ActivityManager.getCurrentUser();
-            mScreenLocked = true;
+                mCurrentOemFunctions = SystemProperties.get(UsbDeviceManager.getPersistProp(false),
+                        UsbManager.USB_FUNCTION_NONE);
+                if (isNormalBoot()) {
+                    mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
+                            UsbManager.USB_FUNCTION_NONE);
+                    mCurrentFunctionsApplied = mCurrentFunctions.equals(
+                            SystemProperties.get(USB_STATE_PROPERTY));
+                } else {
+                    mCurrentFunctions = SystemProperties.get(getPersistProp(true),
+                            UsbManager.USB_FUNCTION_NONE);
+                    mCurrentFunctionsApplied = SystemProperties.get(USB_CONFIG_PROPERTY,
+                            UsbManager.USB_FUNCTION_NONE).equals(
+                            SystemProperties.get(USB_STATE_PROPERTY));
+                }
 
-            /*
-             * Use the normal bootmode persistent prop to maintain state of adb across
-             * all boot modes.
-             */
-            mAdbEnabled = UsbManager.containsFunction(
-                    SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY),
-                    UsbManager.USB_FUNCTION_ADB);
+                /*
+                 * Use the normal bootmode persistent prop to maintain state of adb across
+                 * all boot modes.
+                 */
+                mAdbEnabled = UsbManager.containsFunction(
+                        SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY),
+                        UsbManager.USB_FUNCTION_ADB);
 
-            /*
-             * Previous versions can set persist config to mtp/ptp but it does not
-             * get reset on OTA. Reset the property here instead.
-             */
-            String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
-            if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)
-                    || UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) {
-                SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
-                        UsbManager.removeFunction(UsbManager.removeFunction(persisted,
-                                UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP));
+                /*
+                 * Previous versions can set persist config to mtp/ptp but it does not
+                 * get reset on OTA. Reset the property here instead.
+                 */
+                String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
+                if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)
+                        || UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) {
+                    SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
+                            UsbManager.removeFunction(UsbManager.removeFunction(persisted,
+                                    UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP));
+                }
+
+                String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
+                updateState(state);
+
+                // register observer to listen for settings changes
+                mContentResolver.registerContentObserver(
+                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
+                        false, new AdbSettingsObserver());
+
+                // Watch for USB configuration changes
+                mUEventObserver.startObserving(USB_STATE_MATCH);
+                mUEventObserver.startObserving(ACCESSORY_START_MATCH);
+            } catch (Exception e) {
+                Slog.e(TAG, "Error initializing UsbHandler", e);
             }
         }
 
@@ -543,21 +507,6 @@
             sendMessage(m);
         }
 
-        public void sendMessage(int what, boolean arg1, boolean arg2) {
-            removeMessages(what);
-            Message m = Message.obtain(this, what);
-            m.arg1 = (arg1 ? 1 : 0);
-            m.arg2 = (arg2 ? 1 : 0);
-            sendMessage(m);
-        }
-
-        public void sendMessageDelayed(int what, boolean arg, long delayMillis) {
-            removeMessages(what);
-            Message m = Message.obtain(this, what);
-            m.arg1 = (arg ? 1 : 0);
-            sendMessageDelayed(m, delayMillis);
-        }
-
         public void updateState(String state) {
             int connected, configured;
 
@@ -575,7 +524,6 @@
                 return;
             }
             removeMessages(MSG_UPDATE_STATE);
-            if (connected == 1) removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
             Message msg = Message.obtain(this, MSG_UPDATE_STATE);
             msg.arg1 = connected;
             msg.arg2 = configured;
@@ -598,6 +546,28 @@
             sendMessageDelayed(msg, UPDATE_DELAY);
         }
 
+        private boolean waitForState(String state) {
+            // wait for the transition to complete.
+            // give up after 1 second.
+            String value = null;
+            for (int i = 0; i < 20; i++) {
+                // State transition is done when sys.usb.state is set to the new configuration
+                value = SystemProperties.get(USB_STATE_PROPERTY);
+                if (state.equals(value)) return true;
+                SystemClock.sleep(50);
+            }
+            Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value);
+            return false;
+        }
+
+        private void setUsbConfig(String config) {
+            if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
+            // set the new configuration
+            // we always set it due to b/23631400, where adbd was getting killed
+            // and not restarted due to property timeouts on some devices
+            SystemProperties.set(USB_CONFIG_PROPERTY, config);
+        }
+
         private void setAdbEnabled(boolean enable) {
             if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
             if (enable != mAdbEnabled) {
@@ -624,7 +594,114 @@
             }
         }
 
-        protected String applyAdbFunction(String functions) {
+        /**
+         * Evaluates USB function policies and applies the change accordingly.
+         */
+        private void setEnabledFunctions(String functions, boolean forceRestart,
+                boolean usbDataUnlocked) {
+            if (DEBUG) {
+                Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
+                        + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
+            }
+
+            if (usbDataUnlocked != mUsbDataUnlocked) {
+                mUsbDataUnlocked = usbDataUnlocked;
+                updateUsbNotification(false);
+                forceRestart = true;
+            }
+
+            // Try to set the enabled functions.
+            final String oldFunctions = mCurrentFunctions;
+            final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
+            if (trySetEnabledFunctions(functions, forceRestart)) {
+                return;
+            }
+
+            // Didn't work.  Try to revert changes.
+            // We always reapply the policy in case certain constraints changed such as
+            // user restrictions independently of any other new functions we were
+            // trying to activate.
+            if (oldFunctionsApplied && !oldFunctions.equals(functions)) {
+                Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
+                if (trySetEnabledFunctions(oldFunctions, false)) {
+                    return;
+                }
+            }
+
+            // Still didn't work.  Try to restore the default functions.
+            Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
+            if (trySetEnabledFunctions(null, false)) {
+                return;
+            }
+
+            // Now we're desperate.  Ignore the default functions.
+            // Try to get ADB working if enabled.
+            Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
+            if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) {
+                return;
+            }
+
+            // Ouch.
+            Slog.e(TAG, "Unable to set any USB functions!");
+        }
+
+        private boolean isNormalBoot() {
+            String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+            return bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown");
+        }
+
+        private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
+            if (functions == null || applyAdbFunction(functions)
+                    .equals(UsbManager.USB_FUNCTION_NONE)) {
+                functions = getDefaultFunctions();
+            }
+            functions = applyAdbFunction(functions);
+
+            String oemFunctions = applyOemOverrideFunction(functions);
+
+            if (!isNormalBoot() && !mCurrentFunctions.equals(functions)) {
+                SystemProperties.set(getPersistProp(true), functions);
+            }
+
+            if ((!functions.equals(oemFunctions) &&
+                            !mCurrentOemFunctions.equals(oemFunctions))
+                    || !mCurrentFunctions.equals(functions)
+                    || !mCurrentFunctionsApplied
+                    || forceRestart) {
+                Slog.i(TAG, "Setting USB config to " + functions);
+                mCurrentFunctions = functions;
+                mCurrentOemFunctions = oemFunctions;
+                mCurrentFunctionsApplied = false;
+
+                // Kick the USB stack to close existing connections.
+                setUsbConfig(UsbManager.USB_FUNCTION_NONE);
+
+                if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
+                    Slog.e(TAG, "Failed to kick USB config");
+                    return false;
+                }
+
+                // Set the new USB configuration.
+                setUsbConfig(oemFunctions);
+
+                if (mBootCompleted
+                        && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
+                        || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
+                    // Start up dependent services.
+                    updateUsbStateBroadcastIfNeeded(true);
+                }
+
+                if (!waitForState(oemFunctions)) {
+                    Slog.e(TAG, "Failed to switch USB config to " + functions);
+                    return false;
+                }
+
+                mCurrentFunctionsApplied = true;
+            }
+            return true;
+        }
+
+        private String applyAdbFunction(String functions) {
             // Do not pass null pointer to the UsbManager.
             // There isnt a check there.
             if (functions == null) {
@@ -706,7 +783,7 @@
             return false;
         }
 
-        protected void updateUsbStateBroadcastIfNeeded(boolean configChanged) {
+        private void updateUsbStateBroadcastIfNeeded(boolean configChanged) {
             // send a sticky broadcast containing current USB state
             Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
@@ -799,14 +876,6 @@
                     mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
         }
 
-        private void setScreenUnlockedFunctions() {
-            setEnabledFunctions(mScreenUnlockedFunctions, false,
-                    UsbManager.containsFunction(mScreenUnlockedFunctions,
-                            UsbManager.USB_FUNCTION_MTP)
-                            || UsbManager.containsFunction(mScreenUnlockedFunctions,
-                            UsbManager.USB_FUNCTION_PTP));
-        }
-
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -824,16 +893,9 @@
                         updateCurrentAccessory();
                     }
                     if (mBootCompleted) {
-                        if (!mConnected && !hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT)
-                                && !hasMessages(MSG_FUNCTION_SWITCH_TIMEOUT)) {
+                        if (!mConnected && !hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT)) {
                             // restore defaults when USB is disconnected
-                            if (!mScreenLocked
-                                    && !UsbManager.USB_FUNCTION_NONE.equals(
-                                    mScreenUnlockedFunctions)) {
-                                setScreenUnlockedFunctions();
-                            } else {
-                                setEnabledFunctions(null, !mAdbEnabled, false);
-                            }
+                            setEnabledFunctions(null, !mAdbEnabled, false);
                         }
                         updateUsbFunctions();
                     } else {
@@ -916,47 +978,6 @@
                     String functions = (String) msg.obj;
                     setEnabledFunctions(functions, false, msg.arg1 == 1);
                     break;
-                case MSG_SET_SCREEN_UNLOCKED_FUNCTIONS:
-                    mScreenUnlockedFunctions = (String) msg.obj;
-                    SharedPreferences.Editor editor = mSettings.edit();
-                    editor.putString(String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF,
-                            mCurrentUser), mScreenUnlockedFunctions);
-                    editor.commit();
-                    if (!mScreenLocked && !UsbManager.USB_FUNCTION_NONE.equals(
-                            mScreenUnlockedFunctions)) {
-                        // If the screen is unlocked, also set current functions.
-                        setScreenUnlockedFunctions();
-                    }
-                    break;
-                case MSG_UPDATE_SCREEN_LOCK:
-                    if (msg.arg1 == 1 == mScreenLocked) {
-                        break;
-                    }
-                    mScreenLocked = msg.arg1 == 1;
-                    if (mSettings == null && !mScreenLocked) {
-                        // Shared preferences aren't accessible until the user has been unlocked.
-                        mSettings = getPinnedSharedPrefs(mContext);
-                        mScreenUnlockedFunctions = mSettings.getString(
-                                String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
-                                UsbManager.USB_FUNCTION_NONE);
-                    }
-                    if (!mBootCompleted) {
-                        break;
-                    }
-                    if (mScreenLocked) {
-                        if (!mConnected) {
-                            setEnabledFunctions(null, false, false);
-                        }
-                    } else {
-                        if (!UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)
-                                && (UsbManager.USB_FUNCTION_ADB.equals(mCurrentFunctions)
-                                || (UsbManager.USB_FUNCTION_MTP.equals(mCurrentFunctions)
-                                && !mUsbDataUnlocked))) {
-                            // Set the screen unlocked functions if current function is charging.
-                            setScreenUnlockedFunctions();
-                        }
-                    }
-                    break;
                 case MSG_UPDATE_USER_RESTRICTIONS:
                     // Restart the USB stack if USB transfer is enabled but no longer allowed.
                     final boolean forceRestart = mUsbDataUnlocked
@@ -966,8 +987,9 @@
                             mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart);
                     break;
                 case MSG_SYSTEM_READY:
-                    mSystemReady = true;
-                    finishBoot();
+                    updateUsbNotification(false);
+                    updateAdbNotification(false);
+                    updateUsbFunctions();
                     break;
                 case MSG_LOCALE_CHANGED:
                     updateAdbNotification(true);
@@ -975,19 +997,30 @@
                     break;
                 case MSG_BOOT_COMPLETED:
                     mBootCompleted = true;
-                    finishBoot();
+                    if (mPendingBootBroadcast) {
+                        updateUsbStateBroadcastIfNeeded(false);
+                        mPendingBootBroadcast = false;
+                    }
+                    setEnabledFunctions(null, false, false);
+                    if (mCurrentAccessory != null) {
+                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
+                    }
+                    if (mDebuggingManager != null) {
+                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
+                    }
                     break;
                 case MSG_USER_SWITCHED: {
                     if (mCurrentUser != msg.arg1) {
-                        if (DEBUG) {
-                            Slog.v(TAG, "Current user switched to " + msg.arg1);
+                        // Restart the USB stack and re-apply user restrictions for MTP or PTP.
+                        if (mUsbDataUnlocked
+                                && isUsbDataTransferActive()
+                                && mCurrentUser != UserHandle.USER_NULL) {
+                            Slog.v(TAG, "Current user switched to " + msg.arg1
+                                    + "; resetting USB host stack for MTP or PTP");
+                            // avoid leaking sensitive data from previous user
+                            setEnabledFunctions(null, true, false);
                         }
                         mCurrentUser = msg.arg1;
-                        mScreenLocked = true;
-                        mScreenUnlockedFunctions = mSettings.getString(
-                                String.format(Locale.ENGLISH, UNLOCKED_CONFIG_PREF, mCurrentUser),
-                                UsbManager.USB_FUNCTION_NONE);
-                        setEnabledFunctions(null, false, false);
                     }
                     break;
                 }
@@ -1005,41 +1038,6 @@
             }
         }
 
-        protected void finishBoot() {
-            if (mBootCompleted && mCurrentUsbFunctionsReceived && mSystemReady) {
-                if (mPendingBootBroadcast) {
-                    updateUsbStateBroadcastIfNeeded(false);
-                    mPendingBootBroadcast = false;
-                }
-                if (!mScreenLocked
-                        && !UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)) {
-                    setScreenUnlockedFunctions();
-                } else {
-                    setEnabledFunctions(null, false, false);
-                }
-                if (mCurrentAccessory != null) {
-                    getCurrentSettings().accessoryAttached(mCurrentAccessory);
-                }
-                if (mDebuggingManager != null) {
-                    mDebuggingManager.setAdbEnabled(mAdbEnabled);
-                }
-
-                // make sure the ADB_ENABLED setting value matches the current state
-                try {
-                    Settings.Global.putInt(mContentResolver,
-                            Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
-                } catch (SecurityException e) {
-                    // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't
-                    // be changed.
-                    Slog.d(TAG, "ADB_ENABLED is restricted.");
-                }
-
-                updateUsbNotification(false);
-                updateAdbNotification(false);
-                updateUsbFunctions();
-            }
-        }
-
         private boolean isUsbDataTransferActive() {
             return UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)
                     || UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP);
@@ -1049,7 +1047,7 @@
             return mCurrentAccessory;
         }
 
-        protected void updateUsbNotification(boolean force) {
+        private void updateUsbNotification(boolean force) {
             if (mNotificationManager == null || !mUseUsbNotification
                     || ("0".equals(SystemProperties.get("persist.charging.notify")))) {
                 return;
@@ -1074,12 +1072,20 @@
                 titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
                 id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
             } else if (mConnected) {
-                if (UsbManager.containsFunction(mCurrentFunctions,
-                        UsbManager.USB_FUNCTION_MTP) && mUsbDataUnlocked) {
+                if (!mUsbDataUnlocked) {
+                    if (mSourcePower) {
+                        titleRes = com.android.internal.R.string.usb_supplying_notification_title;
+                        id = SystemMessage.NOTE_USB_SUPPLYING;
+                    } else {
+                        titleRes = com.android.internal.R.string.usb_charging_notification_title;
+                        id = SystemMessage.NOTE_USB_CHARGING;
+                    }
+                } else if (UsbManager.containsFunction(mCurrentFunctions,
+                        UsbManager.USB_FUNCTION_MTP)) {
                     titleRes = com.android.internal.R.string.usb_mtp_notification_title;
                     id = SystemMessage.NOTE_USB_MTP;
                 } else if (UsbManager.containsFunction(mCurrentFunctions,
-                        UsbManager.USB_FUNCTION_PTP) && mUsbDataUnlocked) {
+                        UsbManager.USB_FUNCTION_PTP)) {
                     titleRes = com.android.internal.R.string.usb_ptp_notification_title;
                     id = SystemMessage.NOTE_USB_PTP;
                 } else if (UsbManager.containsFunction(mCurrentFunctions,
@@ -1149,18 +1155,18 @@
                     }
 
                     Notification.Builder builder = new Notification.Builder(mContext, channel)
-                            .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
-                            .setWhen(0)
-                            .setOngoing(true)
-                            .setTicker(title)
-                            .setDefaults(0)  // please be quiet
-                            .setColor(mContext.getColor(
-                                    com.android.internal.R.color
-                                            .system_notification_accent_color))
-                            .setContentTitle(title)
-                            .setContentText(message)
-                            .setContentIntent(pi)
-                            .setVisibility(Notification.VISIBILITY_PUBLIC);
+                                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                                    .setWhen(0)
+                                    .setOngoing(true)
+                                    .setTicker(title)
+                                    .setDefaults(0)  // please be quiet
+                                    .setColor(mContext.getColor(
+                                            com.android.internal.R.color
+                                                    .system_notification_accent_color))
+                                    .setContentTitle(title)
+                                    .setContentText(message)
+                                    .setContentIntent(pi)
+                                    .setVisibility(Notification.VISIBILITY_PUBLIC);
 
                     if (titleRes
                             == com.android.internal.R.string
@@ -1178,7 +1184,7 @@
             }
         }
 
-        protected void updateAdbNotification(boolean force) {
+        private void updateAdbNotification(boolean force) {
             if (mNotificationManager == null) return;
             final int id = SystemMessage.NOTE_ADB_ACTIVE;
             final int titleRes = com.android.internal.R.string.adb_active_notification_title;
@@ -1230,26 +1236,23 @@
             }
         }
 
-        protected String getChargingFunctions() {
+        private String getDefaultFunctions() {
+            String func = SystemProperties.get(getPersistProp(true),
+                    UsbManager.USB_FUNCTION_NONE);
             // if ADB is enabled, reset functions to ADB
             // else enable MTP as usual.
-            if (mAdbEnabled) {
+            if (UsbManager.containsFunction(func, UsbManager.USB_FUNCTION_ADB)) {
                 return UsbManager.USB_FUNCTION_ADB;
             } else {
                 return UsbManager.USB_FUNCTION_MTP;
             }
         }
 
-        public boolean isFunctionEnabled(String function) {
-            return UsbManager.containsFunction(mCurrentFunctions, function);
-        }
-
         public void dump(IndentingPrintWriter pw) {
             pw.println("USB Device State:");
             pw.println("  mCurrentFunctions: " + mCurrentFunctions);
+            pw.println("  mCurrentOemFunctions: " + mCurrentOemFunctions);
             pw.println("  mCurrentFunctionsApplied: " + mCurrentFunctionsApplied);
-            pw.println("  mScreenUnlockedFunctions: " + mScreenUnlockedFunctions);
-            pw.println("  mScreenLocked: " + mScreenLocked);
             pw.println("  mConnected: " + mConnected);
             pw.println("  mConfigured: " + mConfigured);
             pw.println("  mUsbDataUnlocked: " + mUsbDataUnlocked);
@@ -1260,7 +1263,6 @@
             pw.println("  mUsbCharging: " + mUsbCharging);
             pw.println("  mHideUsbNotification: " + mHideUsbNotification);
             pw.println("  mAudioAccessoryConnected: " + mAudioAccessoryConnected);
-            pw.println("  mAdbEnabled: " + mAdbEnabled);
 
             try {
                 pw.println("  Kernel state: "
@@ -1271,675 +1273,6 @@
                 pw.println("IOException: " + e);
             }
         }
-
-        /**
-         * Evaluates USB function policies and applies the change accordingly.
-         */
-        protected abstract void setEnabledFunctions(String functions, boolean forceRestart,
-                boolean usbDataUnlocked);
-
-    }
-
-    private final class UsbHandlerLegacy extends UsbHandler {
-        /**
-         * The non-persistent property which stores the current USB settings.
-         */
-        private static final String USB_CONFIG_PROPERTY = "sys.usb.config";
-
-        /**
-         * The non-persistent property which stores the current USB actual state.
-         */
-        private static final String USB_STATE_PROPERTY = "sys.usb.state";
-
-        private HashMap<String, HashMap<String, Pair<String, String>>> mOemModeMap;
-        private String mCurrentOemFunctions;
-
-        UsbHandlerLegacy(Looper looper, Context context) {
-            super(looper);
-            try {
-                readOemUsbOverrideConfig(context);
-                // Restore default functions.
-                mCurrentOemFunctions = SystemProperties.get(getPersistProp(false),
-                        UsbManager.USB_FUNCTION_NONE);
-                if (isNormalBoot()) {
-                    mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
-                            UsbManager.USB_FUNCTION_NONE);
-                    mCurrentFunctionsApplied = mCurrentFunctions.equals(
-                            SystemProperties.get(USB_STATE_PROPERTY));
-                } else {
-                    mCurrentFunctions = SystemProperties.get(getPersistProp(true),
-                            UsbManager.USB_FUNCTION_NONE);
-                    mCurrentFunctionsApplied = SystemProperties.get(USB_CONFIG_PROPERTY,
-                            UsbManager.USB_FUNCTION_NONE).equals(
-                            SystemProperties.get(USB_STATE_PROPERTY));
-                }
-                mCurrentUsbFunctionsReceived = true;
-
-                String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
-                updateState(state);
-
-                // register observer to listen for settings changes
-                mContentResolver.registerContentObserver(
-                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
-                        false, new AdbSettingsObserver());
-
-                // Watch for USB configuration changes
-                mUEventObserver.startObserving(USB_STATE_MATCH);
-                mUEventObserver.startObserving(ACCESSORY_START_MATCH);
-            } catch (Exception e) {
-                Slog.e(TAG, "Error initializing UsbHandler", e);
-            }
-        }
-
-        private void readOemUsbOverrideConfig(Context context) {
-            String[] configList = mContext.getResources().getStringArray(
-                    com.android.internal.R.array.config_oemUsbModeOverride);
-
-            if (configList != null) {
-                for (String config : configList) {
-                    String[] items = config.split(":");
-                    if (items.length == 3 || items.length == 4) {
-                        if (mOemModeMap == null) {
-                            mOemModeMap = new HashMap<>();
-                        }
-                        HashMap<String, Pair<String, String>> overrideMap =
-                                mOemModeMap.get(items[0]);
-                        if (overrideMap == null) {
-                            overrideMap = new HashMap<>();
-                            mOemModeMap.put(items[0], overrideMap);
-                        }
-
-                        // Favoring the first combination if duplicate exists
-                        if (!overrideMap.containsKey(items[1])) {
-                            if (items.length == 3) {
-                                overrideMap.put(items[1], new Pair<>(items[2], ""));
-                            } else {
-                                overrideMap.put(items[1], new Pair<>(items[2], items[3]));
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        private String applyOemOverrideFunction(String usbFunctions) {
-            if ((usbFunctions == null) || (mOemModeMap == null)) {
-                return usbFunctions;
-            }
-
-            String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
-            Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode);
-
-            Map<String, Pair<String, String>> overridesMap =
-                    mOemModeMap.get(bootMode);
-            // Check to ensure that the oem is not overriding in the normal
-            // boot mode
-            if (overridesMap != null && !(bootMode.equals(NORMAL_BOOT)
-                    || bootMode.equals("unknown"))) {
-                Pair<String, String> overrideFunctions =
-                        overridesMap.get(usbFunctions);
-                if (overrideFunctions != null) {
-                    Slog.d(TAG, "OEM USB override: " + usbFunctions
-                            + " ==> " + overrideFunctions.first
-                            + " persist across reboot "
-                            + overrideFunctions.second);
-                    if (!overrideFunctions.second.equals("")) {
-                        String newFunction;
-                        if (mAdbEnabled) {
-                            newFunction = UsbManager.addFunction(overrideFunctions.second,
-                                    UsbManager.USB_FUNCTION_ADB);
-                        } else {
-                            newFunction = overrideFunctions.second;
-                        }
-                        Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: "
-                                + getPersistProp(false));
-                        SystemProperties.set(getPersistProp(false),
-                                newFunction);
-                    }
-                    return overrideFunctions.first;
-                } else if (mAdbEnabled) {
-                    String newFunction = UsbManager.addFunction(UsbManager.USB_FUNCTION_NONE,
-                            UsbManager.USB_FUNCTION_ADB);
-                    SystemProperties.set(getPersistProp(false),
-                            newFunction);
-                } else {
-                    SystemProperties.set(getPersistProp(false),
-                            UsbManager.USB_FUNCTION_NONE);
-                }
-            }
-            // return passed in functions as is.
-            return usbFunctions;
-        }
-
-        private boolean waitForState(String state) {
-            // wait for the transition to complete.
-            // give up after 1 second.
-            String value = null;
-            for (int i = 0; i < 20; i++) {
-                // State transition is done when sys.usb.state is set to the new configuration
-                value = SystemProperties.get(USB_STATE_PROPERTY);
-                if (state.equals(value)) return true;
-                SystemClock.sleep(50);
-            }
-            Slog.e(TAG, "waitForState(" + state + ") FAILED: got " + value);
-            return false;
-        }
-
-        private void setUsbConfig(String config) {
-            if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
-            /**
-             * set the new configuration
-             * we always set it due to b/23631400, where adbd was getting killed
-             * and not restarted due to property timeouts on some devices
-             */
-            SystemProperties.set(USB_CONFIG_PROPERTY, config);
-        }
-
-        @Override
-        protected void setEnabledFunctions(String functions, boolean forceRestart,
-                boolean usbDataUnlocked) {
-            if (DEBUG) {
-                Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
-                        + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
-            }
-
-            if (usbDataUnlocked != mUsbDataUnlocked) {
-                mUsbDataUnlocked = usbDataUnlocked;
-                updateUsbNotification(false);
-                forceRestart = true;
-            }
-
-            /**
-             * Try to set the enabled functions.
-             */
-            final String oldFunctions = mCurrentFunctions;
-            final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
-            if (trySetEnabledFunctions(functions, forceRestart)) {
-                return;
-            }
-
-            /**
-             * Didn't work.  Try to revert changes.
-             * We always reapply the policy in case certain constraints changed such as
-             * user restrictions independently of any other new functions we were
-             * trying to activate.
-             */
-            if (oldFunctionsApplied && !oldFunctions.equals(functions)) {
-                Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
-                if (trySetEnabledFunctions(oldFunctions, false)) {
-                    return;
-                }
-            }
-
-            /**
-             * Still didn't work.  Try to restore the default functions.
-             */
-            Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
-            if (trySetEnabledFunctions(null, false)) {
-                return;
-            }
-
-            /**
-             * Now we're desperate.  Ignore the default functions.
-             * Try to get ADB working if enabled.
-             */
-            Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
-            if (trySetEnabledFunctions(UsbManager.USB_FUNCTION_NONE, false)) {
-                return;
-            }
-
-            /**
-             * Ouch.
-             */
-            Slog.e(TAG, "Unable to set any USB functions!");
-        }
-
-        private boolean isNormalBoot() {
-            String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
-            return bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown");
-        }
-
-        private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
-            if (functions == null || applyAdbFunction(functions)
-                    .equals(UsbManager.USB_FUNCTION_NONE)) {
-                functions = getChargingFunctions();
-            }
-            functions = applyAdbFunction(functions);
-
-            String oemFunctions = applyOemOverrideFunction(functions);
-
-            if (!isNormalBoot() && !mCurrentFunctions.equals(functions)) {
-                SystemProperties.set(getPersistProp(true), functions);
-            }
-
-            if ((!functions.equals(oemFunctions)
-                    && !mCurrentOemFunctions.equals(oemFunctions))
-                    || !mCurrentFunctions.equals(functions)
-                    || !mCurrentFunctionsApplied
-                    || forceRestart) {
-                Slog.i(TAG, "Setting USB config to " + functions);
-                mCurrentFunctions = functions;
-                mCurrentOemFunctions = oemFunctions;
-                mCurrentFunctionsApplied = false;
-
-                /**
-                 * Kick the USB stack to close existing connections.
-                 */
-                setUsbConfig(UsbManager.USB_FUNCTION_NONE);
-
-                if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
-                    Slog.e(TAG, "Failed to kick USB config");
-                    return false;
-                }
-
-                /**
-                 * Set the new USB configuration.
-                 */
-                setUsbConfig(oemFunctions);
-
-                if (mBootCompleted
-                        && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
-                        || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
-                    /**
-                     * Start up dependent services.
-                     */
-                    updateUsbStateBroadcastIfNeeded(true);
-                }
-
-                if (!waitForState(oemFunctions)) {
-                    Slog.e(TAG, "Failed to switch USB config to " + functions);
-                    return false;
-                }
-
-                mCurrentFunctionsApplied = true;
-            }
-            return true;
-        }
-
-        private String getPersistProp(boolean functions) {
-            String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
-            String persistProp = USB_PERSISTENT_CONFIG_PROPERTY;
-            if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) {
-                if (functions) {
-                    persistProp = "persist.sys.usb." + bootMode + ".func";
-                } else {
-                    persistProp = "persist.sys.usb." + bootMode + ".config";
-                }
-            }
-            return persistProp;
-        }
-    }
-
-    private final class UsbHandlerHal extends UsbHandler {
-
-        /**
-         * Proxy object for the usb gadget hal daemon.
-         */
-        @GuardedBy("mGadgetProxyLock")
-        private IUsbGadget mGadgetProxy;
-
-        private final Object mGadgetProxyLock = new Object();
-
-        /**
-         * Cookie sent for usb gadget hal death notification.
-         */
-        private static final int USB_GADGET_HAL_DEATH_COOKIE = 2000;
-
-        /**
-         * Keeps track of the latest setCurrentUsbFunctions request number.
-         */
-        private int mCurrentRequest = 0;
-
-        /**
-         * The maximum time for which the UsbDeviceManager would wait once
-         * setCurrentUsbFunctions is called.
-         */
-        private static final int SET_FUNCTIONS_TIMEOUT_MS = 3000;
-
-        /**
-         * Conseration leeway to make sure that the hal callback arrives before
-         * SET_FUNCTIONS_TIMEOUT_MS expires. If the callback does not arrive
-         * within SET_FUNCTIONS_TIMEOUT_MS, UsbDeviceManager retries enabling
-         * default functions.
-         */
-        private static final int SET_FUNCTIONS_LEEWAY_MS = 500;
-
-        /**
-         * While switching functions, a disconnect is excpect as the usb gadget
-         * us torn down and brought back up. Wait for SET_FUNCTIONS_TIMEOUT_MS +
-         * ENUMERATION_TIME_OUT_MS before switching back to default fumctions when
-         * switching functions.
-         */
-        private static final int ENUMERATION_TIME_OUT_MS = 2000;
-
-        /**
-         * Command to start native service.
-         */
-        protected static final String CTL_START = "ctl.start";
-
-        /**
-         * Command to start native service.
-         */
-        protected static final String CTL_STOP = "ctl.stop";
-
-        /**
-         * Adb natvie daemon
-         */
-        protected static final String ADBD = "adbd";
-
-
-        UsbHandlerHal(Looper looper) {
-            super(looper);
-            try {
-                ServiceNotification serviceNotification = new ServiceNotification();
-
-                boolean ret = IServiceManager.getService()
-                        .registerForNotifications("android.hardware.usb.gadget@1.0::IUsbGadget",
-                                "", serviceNotification);
-                if (!ret) {
-                    Slog.e(TAG, "Failed to register usb gadget service start notification");
-                    return;
-                }
-
-                synchronized (mGadgetProxyLock) {
-                    mGadgetProxy = IUsbGadget.getService(true);
-                    mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
-                            USB_GADGET_HAL_DEATH_COOKIE);
-                    mCurrentFunctions = UsbManager.USB_FUNCTION_NONE;
-                    mGadgetProxy.getCurrentUsbFunctions(new UsbGadgetCallback());
-                    mCurrentUsbFunctionsRequested = true;
-                }
-                String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
-                updateState(state);
-
-                /**
-                 * Register observer to listen for settings changes.
-                 */
-                mContentResolver.registerContentObserver(
-                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
-                        false, new AdbSettingsObserver());
-
-                /**
-                 * Watch for USB configuration changes.
-                 */
-                mUEventObserver.startObserving(USB_STATE_MATCH);
-                mUEventObserver.startObserving(ACCESSORY_START_MATCH);
-            } catch (NoSuchElementException e) {
-                Slog.e(TAG, "Usb gadget hal not found", e);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Usb Gadget hal not responding", e);
-            } catch (Exception e) {
-                Slog.e(TAG, "Error initializing UsbHandler", e);
-            }
-        }
-
-
-        final class UsbGadgetDeathRecipient implements HwBinder.DeathRecipient {
-            @Override
-            public void serviceDied(long cookie) {
-                if (cookie == USB_GADGET_HAL_DEATH_COOKIE) {
-                    Slog.e(TAG, "Usb Gadget hal service died cookie: " + cookie);
-                    synchronized (mGadgetProxyLock) {
-                        mGadgetProxy = null;
-                    }
-                }
-            }
-        }
-
-        final class ServiceNotification extends IServiceNotification.Stub {
-            @Override
-            public void onRegistration(String fqName, String name, boolean preexisting) {
-                Slog.i(TAG, "Usb gadget hal service started " + fqName + " " + name);
-                synchronized (mGadgetProxyLock) {
-                    try {
-                        mGadgetProxy = IUsbGadget.getService();
-                        mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
-                                USB_GADGET_HAL_DEATH_COOKIE);
-                        if (!mCurrentFunctionsApplied) {
-                            setCurrentFunctions(mCurrentFunctions, mUsbDataUnlocked);
-                        }
-                    } catch (NoSuchElementException e) {
-                        Slog.e(TAG, "Usb gadget hal not found", e);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Usb Gadget hal not responding", e);
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_SET_CHARGING_FUNCTIONS:
-                    setEnabledFunctions(null, false, mUsbDataUnlocked);
-                    break;
-                case MSG_SET_FUNCTIONS_TIMEOUT:
-                    Slog.e(TAG, "Set functions timed out! no reply from usb hal");
-                    if (msg.arg1 != 1) {
-                        setEnabledFunctions(null, false, mUsbDataUnlocked);
-                    }
-                    break;
-                case MSG_GET_CURRENT_USB_FUNCTIONS:
-                    Slog.e(TAG, "prcessing MSG_GET_CURRENT_USB_FUNCTIONS");
-                    mCurrentUsbFunctionsReceived = true;
-
-                    if (mCurrentUsbFunctionsRequested) {
-                        Slog.e(TAG, "updating mCurrentFunctions");
-                        mCurrentFunctions = functionListToString((Long) msg.obj);
-                        Slog.e(TAG,
-                                "mCurrentFunctions:" + mCurrentFunctions + "applied:" + msg.arg1);
-                        mCurrentFunctionsApplied = msg.arg1 == 1;
-                    }
-                    finishBoot();
-                    break;
-                case MSG_FUNCTION_SWITCH_TIMEOUT:
-                    /**
-                     * Dont force to default when the configuration is already set to default.
-                     */
-                    if (msg.arg1 != 1) {
-                        setEnabledFunctions(null, !mAdbEnabled, false);
-                    }
-                    break;
-                default:
-                    super.handleMessage(msg);
-            }
-        }
-
-        private class UsbGadgetCallback extends IUsbGadgetCallback.Stub {
-            int mRequest;
-            long mFunctions;
-            boolean mChargingFunctions;
-
-            UsbGadgetCallback() {
-            }
-
-            UsbGadgetCallback(int request, long functions,
-                    boolean chargingFunctions) {
-                mRequest = request;
-                mFunctions = functions;
-                mChargingFunctions = chargingFunctions;
-            }
-
-            @Override
-            public void setCurrentUsbFunctionsCb(long functions,
-                    int status) {
-                /**
-                 * Callback called for a previous setCurrenUsbFunction
-                 */
-                if ((mCurrentRequest != mRequest) || !hasMessages(MSG_SET_FUNCTIONS_TIMEOUT)
-                        || (mFunctions != functions)) {
-                    return;
-                }
-
-                removeMessages(MSG_SET_FUNCTIONS_TIMEOUT);
-                Slog.e(TAG, "notifyCurrentFunction request:" + mRequest + " status:" + status);
-                if (status == Status.SUCCESS) {
-                    mCurrentFunctionsApplied = true;
-                } else if (!mChargingFunctions) {
-                    Slog.e(TAG, "Setting default fuctions");
-                    sendEmptyMessage(MSG_SET_CHARGING_FUNCTIONS);
-                }
-            }
-
-            @Override
-            public void getCurrentUsbFunctionsCb(long functions,
-                    int status) {
-                sendMessage(MSG_GET_CURRENT_USB_FUNCTIONS, functions,
-                        status == Status.FUNCTIONS_APPLIED);
-            }
-        }
-
-        private long stringToFunctionList(String config) {
-            long functionsMask = 0;
-            String[] functions = config.split(",");
-            for (int i = 0; i < functions.length; i++) {
-                switch (functions[i]) {
-                    case "none":
-                        functionsMask |= GadgetFunction.NONE;
-                        break;
-                    case "adb":
-                        functionsMask |= GadgetFunction.ADB;
-                        break;
-                    case "mtp":
-                        functionsMask |= GadgetFunction.MTP;
-                        break;
-                    case "ptp":
-                        functionsMask |= GadgetFunction.PTP;
-                        break;
-                    case "midi":
-                        functionsMask |= GadgetFunction.MIDI;
-                        break;
-                    case "accessory":
-                        functionsMask |= GadgetFunction.ACCESSORY;
-                        break;
-                    case "rndis":
-                        functionsMask |= GadgetFunction.RNDIS;
-                        break;
-                }
-            }
-            return functionsMask;
-        }
-
-        private String functionListToString(Long functionList) {
-            StringJoiner functions = new StringJoiner(",");
-            if (functionList == GadgetFunction.NONE) {
-                functions.add("none");
-                return functions.toString();
-            }
-            if ((functionList & GadgetFunction.ADB) != 0) {
-                functions.add("adb");
-            }
-            if ((functionList & GadgetFunction.MTP) != 0) {
-                functions.add("mtp");
-            }
-            if ((functionList & GadgetFunction.PTP) != 0) {
-                functions.add("ptp");
-            }
-            if ((functionList & GadgetFunction.MIDI) != 0) {
-                functions.add("midi");
-            }
-            if ((functionList & GadgetFunction.ACCESSORY) != 0) {
-                functions.add("accessory");
-            }
-            if ((functionList & GadgetFunction.RNDIS) != 0) {
-                functions.add("rndis");
-            }
-            /**
-             * Remove the trailing comma.
-             */
-            return functions.toString();
-        }
-
-
-        private void setUsbConfig(String config, boolean chargingFunctions) {
-            Long functions = stringToFunctionList(config);
-            if (true) Slog.d(TAG, "setUsbConfig(" + config + ") request:" + ++mCurrentRequest);
-            /**
-             * Cancel any ongoing requests, if present.
-             */
-            removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
-            removeMessages(MSG_SET_FUNCTIONS_TIMEOUT);
-            removeMessages(MSG_SET_CHARGING_FUNCTIONS);
-
-            synchronized (mGadgetProxyLock) {
-                if (mGadgetProxy == null) {
-                    Slog.e(TAG, "setUsbConfig mGadgetProxy is null");
-                    return;
-                }
-                try {
-                    if ((functions & GadgetFunction.ADB) != 0) {
-                        /**
-                         * Start adbd if ADB function is included in the configuration.
-                         */
-                        SystemProperties.set(CTL_START, ADBD);
-                    } else {
-                        /**
-                         * Stop adbd otherwise.
-                         */
-                        SystemProperties.set(CTL_STOP, ADBD);
-                    }
-                    UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest,
-                            functions, chargingFunctions);
-                    mGadgetProxy.setCurrentUsbFunctions(functions, usbGadgetCallback,
-                            SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS);
-                    sendMessageDelayed(MSG_SET_FUNCTIONS_TIMEOUT, chargingFunctions,
-                            SET_FUNCTIONS_TIMEOUT_MS);
-                    sendMessageDelayed(MSG_FUNCTION_SWITCH_TIMEOUT, chargingFunctions,
-                            SET_FUNCTIONS_TIMEOUT_MS + ENUMERATION_TIME_OUT_MS);
-                    if (DEBUG) Slog.d(TAG, "timeout message queued");
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remoteexception while calling setCurrentUsbFunctions", e);
-                }
-            }
-        }
-
-        @Override
-        protected void setEnabledFunctions(String functions, boolean forceRestart,
-                boolean usbDataUnlocked) {
-            if (DEBUG) {
-                Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", "
-                        + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
-            }
-
-            if (usbDataUnlocked != mUsbDataUnlocked) {
-                mUsbDataUnlocked = usbDataUnlocked;
-                updateUsbNotification(false);
-                forceRestart = true;
-            }
-
-            trySetEnabledFunctions(functions, forceRestart);
-        }
-
-        private void trySetEnabledFunctions(String functions, boolean forceRestart) {
-            boolean chargingFunctions = false;
-
-            if (functions == null || applyAdbFunction(functions)
-                    .equals(UsbManager.USB_FUNCTION_NONE)) {
-                functions = getChargingFunctions();
-                chargingFunctions = true;
-            }
-            functions = applyAdbFunction(functions);
-
-            if (!mCurrentFunctions.equals(functions)
-                    || !mCurrentFunctionsApplied
-                    || forceRestart) {
-                Slog.i(TAG, "Setting USB config to " + functions);
-                mCurrentFunctions = functions;
-                mCurrentFunctionsApplied = false;
-                // set the flag to false as that would be stale value
-                mCurrentUsbFunctionsRequested = false;
-
-                // Set the new USB configuration.
-                setUsbConfig(mCurrentFunctions, chargingFunctions);
-
-                if (mBootCompleted
-                        && (UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
-                        || UsbManager.containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
-                    // Start up dependent services.
-                    updateUsbStateBroadcastIfNeeded(true);
-                }
-            }
-        }
     }
 
     /* returns the currently attached USB accessory */
@@ -1947,11 +1280,7 @@
         return mHandler.getCurrentAccessory();
     }
 
-    /**
-     * opens the currently attached USB accessory.
-     *
-     * @param accessory accessory to be openened.
-     */
+    /* opens the currently attached USB accessory */
     public ParcelFileDescriptor openAccessory(UsbAccessory accessory,
             UsbUserSettingsManager settings) {
         UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
@@ -1968,41 +1297,113 @@
         return nativeOpenAccessory();
     }
 
-    /**
-     * Checks whether the function is present in the USB configuration.
-     *
-     * @param function function to be checked.
-     */
     public boolean isFunctionEnabled(String function) {
-        return mHandler.isFunctionEnabled(function);
+        return UsbManager.containsFunction(SystemProperties.get(USB_CONFIG_PROPERTY), function);
     }
 
-    /**
-     * Adds function to the current USB configuration.
-     *
-     * @param functions name of the USB function, or null to restore the default function.
-     * @param usbDataUnlocked whether user data is accessible.
-     */
     public void setCurrentFunctions(String functions, boolean usbDataUnlocked) {
         if (DEBUG) {
-            Slog.d(TAG, "setCurrentFunctions(" + functions + ", "
-                    + usbDataUnlocked + ")");
+            Slog.d(TAG, "setCurrentFunctions(" + functions + ", " +
+                    usbDataUnlocked + ")");
         }
         mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, usbDataUnlocked);
     }
 
-    /**
-     * Sets the functions which are set when the screen is unlocked.
-     *
-     * @param functions Functions to set.
-     */
-    public void setScreenUnlockedFunctions(String functions) {
-        if (DEBUG) {
-            Slog.d(TAG, "setScreenUnlockedFunctions(" + functions + ")");
+    private void readOemUsbOverrideConfig() {
+        String[] configList = mContext.getResources().getStringArray(
+                com.android.internal.R.array.config_oemUsbModeOverride);
+
+        if (configList != null) {
+            for (String config : configList) {
+                String[] items = config.split(":");
+                if (items.length == 3 || items.length == 4) {
+                    if (mOemModeMap == null) {
+                        mOemModeMap = new HashMap<>();
+                    }
+                    HashMap<String, Pair<String, String>> overrideMap
+                            = mOemModeMap.get(items[0]);
+                    if (overrideMap == null) {
+                        overrideMap = new HashMap<>();
+                        mOemModeMap.put(items[0], overrideMap);
+                    }
+
+                    // Favoring the first combination if duplicate exists
+                    if (!overrideMap.containsKey(items[1])) {
+                        if (items.length == 3) {
+                            overrideMap.put(items[1], new Pair<>(items[2], ""));
+                        } else {
+                            overrideMap.put(items[1], new Pair<>(items[2], items[3]));
+                        }
+                    }
+                }
+            }
         }
-        mHandler.sendMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, functions);
     }
 
+    private String applyOemOverrideFunction(String usbFunctions) {
+        if ((usbFunctions == null) || (mOemModeMap == null)) {
+            return usbFunctions;
+        }
+
+        String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+        Slog.d(TAG, "applyOemOverride usbfunctions=" + usbFunctions + " bootmode=" + bootMode);
+
+        Map<String, Pair<String, String>> overridesMap =
+                mOemModeMap.get(bootMode);
+        // Check to ensure that the oem is not overriding in the normal
+        // boot mode
+        if (overridesMap != null && !(bootMode.equals(NORMAL_BOOT) ||
+                bootMode.equals("unknown"))) {
+            Pair<String, String> overrideFunctions =
+                    overridesMap.get(usbFunctions);
+            if (overrideFunctions != null) {
+                Slog.d(TAG, "OEM USB override: " + usbFunctions
+                        + " ==> " + overrideFunctions.first
+                        + " persist across reboot "
+                        + overrideFunctions.second);
+                if (!overrideFunctions.second.equals("")) {
+                    String newFunction;
+                    if (mAdbEnabled) {
+                        newFunction = UsbManager.addFunction(overrideFunctions.second,
+                                UsbManager.USB_FUNCTION_ADB);
+                    } else {
+                        newFunction = overrideFunctions.second;
+                    }
+                    Slog.d(TAG, "OEM USB override persisting: " + newFunction + "in prop: "
+                            + UsbDeviceManager.getPersistProp(false));
+                    SystemProperties.set(UsbDeviceManager.getPersistProp(false),
+                            newFunction);
+                }
+                return overrideFunctions.first;
+            } else if (mAdbEnabled) {
+                String newFunction = UsbManager.addFunction(UsbManager.USB_FUNCTION_NONE,
+                        UsbManager.USB_FUNCTION_ADB);
+                SystemProperties.set(UsbDeviceManager.getPersistProp(false),
+                        newFunction);
+            } else {
+                SystemProperties.set(UsbDeviceManager.getPersistProp(false),
+                        UsbManager.USB_FUNCTION_NONE);
+            }
+        }
+        // return passed in functions as is.
+        return usbFunctions;
+    }
+
+    public static String getPersistProp(boolean functions) {
+        String bootMode = SystemProperties.get(BOOT_MODE_PROPERTY, "unknown");
+        String persistProp = USB_PERSISTENT_CONFIG_PROPERTY;
+        if (!(bootMode.equals(NORMAL_BOOT) || bootMode.equals("unknown"))) {
+            if (functions) {
+                persistProp = "persist.sys.usb." + bootMode + ".func";
+            } else {
+                persistProp = "persist.sys.usb." + bootMode + ".config";
+            }
+        }
+
+        return persistProp;
+    }
+
+
     public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
         if (mDebuggingManager != null) {
             mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 039597c..e4fcea7 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -87,11 +87,6 @@
         public void onStopUser(int userHandle) {
             mUsbService.onStopUser(UserHandle.of(userHandle));
         }
-
-        @Override
-        public void onUnlockUser(int userHandle) {
-            mUsbService.onUnlockUser(userHandle);
-        }
     }
 
     private static final String TAG = "UsbService";
@@ -210,13 +205,6 @@
         }
     }
 
-    /** Called when a user is unlocked. */
-    public void onUnlockUser(int user) {
-        if (mDeviceManager != null) {
-            mDeviceManager.onUnlockUser(user);
-        }
-    }
-
     /* Returns a list of all currently attached USB devices (host mdoe) */
     @Override
     public void getDeviceList(Bundle devices) {
@@ -401,23 +389,6 @@
         }
     }
 
-    @Override
-    public void setScreenUnlockedFunctions(String function) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
-
-        if (!isSupportedCurrentFunction(function)) {
-            Slog.w(TAG, "Caller of setScreenUnlockedFunctions() requested unsupported USB function:"
-                    + function);
-            function = UsbManager.USB_FUNCTION_NONE;
-        }
-
-        if (mDeviceManager != null) {
-            mDeviceManager.setScreenUnlockedFunctions(function);
-        } else {
-            throw new IllegalStateException("USB device mode not supported");
-        }
-    }
-
     private static boolean isSupportedCurrentFunction(String function) {
         if (function == null) return true;