Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22f4a681 authored by Badhri Jagan Sridharan's avatar Badhri Jagan Sridharan Committed by Gerrit Code Review
Browse files

Merge "DO NOT MERGE: Add setScreenUnlockedFunctions method to UsbManager"

parents f0561142 7ca5d3a3
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.commands.svc;

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;
@@ -38,6 +39,9 @@ public class UsbCommand extends Svc.Command {
                + "\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";
    }
@@ -62,6 +66,16 @@ public class UsbCommand extends Svc.Command {
            } 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());
+5 −0
Original line number Diff line number Diff line
@@ -96,6 +96,11 @@ interface IUsbManager
     */
    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.
     */
+26 −0
Original line number Diff line number Diff line
@@ -589,6 +589,32 @@ public class UsbManager {
        }
    }

    /**
     * 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>
+145 −25
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

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;
@@ -26,6 +29,7 @@ import android.content.ContentResolver;
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;
@@ -38,6 +42,7 @@ import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
import android.os.BatteryManager;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -60,6 +65,7 @@ import com.android.internal.notification.SystemNotificationChannels;
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;
@@ -75,7 +81,7 @@ import java.util.Set;
/**
 * UsbDeviceManager manages USB state in device mode.
 */
public class UsbDeviceManager {
public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver {

    private static final String TAG = "UsbDeviceManager";
    private static final boolean DEBUG = false;
@@ -96,6 +102,12 @@ public class UsbDeviceManager {
     */
    private static final String USB_STATE_PROPERTY = "sys.usb.state";

    /**
     * The SharedPreference setting per user that stores the screen unlocked functions between
     * sessions.
     */
    private static final String UNLOCKED_CONFIG_PREF = "usb-screen-unlocked-config-%d";

    /**
     * ro.bootmode value when phone boots into usual Android.
     */
@@ -128,6 +140,8 @@ public class UsbDeviceManager {
    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 AUDIO_MODE_SOURCE = 1;

@@ -169,6 +183,7 @@ public class UsbDeviceManager {
    private Intent mBroadcastedIntent;
    private boolean mPendingBootBroadcast;
    private static Set<Integer> sBlackListedInterfaces;
    private SharedPreferences mSettings;

    static {
        sBlackListedInterfaces = new HashSet<>();
@@ -217,6 +232,31 @@ public class UsbDeviceManager {
        }
    };

    @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;
@@ -303,6 +343,8 @@ public class UsbDeviceManager {
    public void systemReady() {
        if (DEBUG) Slog.d(TAG, "systemReady");

        LocalServices.getService(ActivityManagerInternal.class).registerScreenObserver(this);

        mNotificationManager = (NotificationManager)
                mContext.getSystemService(Context.NOTIFICATION_SERVICE);

@@ -407,6 +449,14 @@ public class UsbDeviceManager {
        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 final class UsbHandler extends Handler {

        // current USB state
@@ -423,11 +473,13 @@ public class UsbDeviceManager {
        private UsbAccessory mCurrentAccessory;
        private int mUsbNotificationId;
        private boolean mAdbNotificationShown;
        private int mCurrentUser = UserHandle.USER_NULL;
        private int mCurrentUser;
        private boolean mUsbCharging;
        private String mCurrentOemFunctions;
        private boolean mHideUsbNotification;
        private boolean mSupportsAllCombinations;
        private String mScreenUnlockedFunctions = UsbManager.USB_FUNCTION_NONE;
        private boolean mScreenLocked;

        public UsbHandler(Looper looper) {
            super(looper);
@@ -449,6 +501,9 @@ public class UsbDeviceManager {
                            SystemProperties.get(USB_STATE_PROPERTY));
                }

                mCurrentUser = ActivityManager.getCurrentUser();
                mScreenLocked = true;

                /*
                 * Use the normal bootmode persistent prop to maintain state of adb across
                 * all boot modes.
@@ -653,7 +708,7 @@ public class UsbDeviceManager {
        private boolean trySetEnabledFunctions(String functions, boolean forceRestart) {
            if (functions == null || applyAdbFunction(functions)
                    .equals(UsbManager.USB_FUNCTION_NONE)) {
                functions = getDefaultFunctions();
                functions = getChargingFunctions();
            }
            functions = applyAdbFunction(functions);

@@ -876,6 +931,14 @@ public class UsbDeviceManager {
                    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) {
@@ -895,8 +958,14 @@ public class UsbDeviceManager {
                    if (mBootCompleted) {
                        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);
                            }
                        }
                        updateUsbFunctions();
                    } else {
                        mPendingBootBroadcast = true;
@@ -978,6 +1047,47 @@ public class UsbDeviceManager {
                    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
@@ -1001,7 +1111,13 @@ public class UsbDeviceManager {
                        updateUsbStateBroadcastIfNeeded(false);
                        mPendingBootBroadcast = false;
                    }

                    if (!mScreenLocked
                            && !UsbManager.USB_FUNCTION_NONE.equals(mScreenUnlockedFunctions)) {
                        setScreenUnlockedFunctions();
                    } else {
                        setEnabledFunctions(null, false, false);
                    }
                    if (mCurrentAccessory != null) {
                        getCurrentSettings().accessoryAttached(mCurrentAccessory);
                    }
@@ -1011,16 +1127,15 @@ public class UsbDeviceManager {
                    break;
                case MSG_USER_SWITCHED: {
                    if (mCurrentUser != 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);
                        if (DEBUG) {
                            Slog.v(TAG, "Current user switched to " + msg.arg1);
                        }
                        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;
                }
@@ -1072,20 +1187,12 @@ public class UsbDeviceManager {
                titleRes = com.android.internal.R.string.usb_unsupported_audio_accessory_title;
                id = SystemMessage.NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED;
            } else if (mConnected) {
                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)) {
                if (UsbManager.containsFunction(mCurrentFunctions,
                        UsbManager.USB_FUNCTION_MTP) && mUsbDataUnlocked) {
                    titleRes = com.android.internal.R.string.usb_mtp_notification_title;
                    id = SystemMessage.NOTE_USB_MTP;
                } else if (UsbManager.containsFunction(mCurrentFunctions,
                        UsbManager.USB_FUNCTION_PTP)) {
                        UsbManager.USB_FUNCTION_PTP) && mUsbDataUnlocked) {
                    titleRes = com.android.internal.R.string.usb_ptp_notification_title;
                    id = SystemMessage.NOTE_USB_PTP;
                } else if (UsbManager.containsFunction(mCurrentFunctions,
@@ -1236,7 +1343,7 @@ public class UsbDeviceManager {
            }
        }

        private String getDefaultFunctions() {
        private String getChargingFunctions() {
            String func = SystemProperties.get(getPersistProp(true),
                    UsbManager.USB_FUNCTION_NONE);
            // if ADB is enabled, reset functions to ADB
@@ -1253,6 +1360,8 @@ public class UsbDeviceManager {
            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);
@@ -1309,6 +1418,17 @@ public class UsbDeviceManager {
        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 + ")");
        }
        mHandler.sendMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, functions);
    }

    private void readOemUsbOverrideConfig() {
        String[] configList = mContext.getResources().getStringArray(
                com.android.internal.R.array.config_oemUsbModeOverride);
+29 −0
Original line number Diff line number Diff line
@@ -87,6 +87,11 @@ public class UsbService extends IUsbManager.Stub {
        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";
@@ -205,6 +210,13 @@ public class UsbService extends IUsbManager.Stub {
        }
    }

    /** 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) {
@@ -389,6 +401,23 @@ public class UsbService extends IUsbManager.Stub {
        }
    }

    @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;