android框架_5.0的USB授权弹框流程分析_011

android5.1的USB授权弹框流程分析

 

一、在UsbDebuggingManager类中

1、文件位置:frameworks/base/services/usb/java/com/android/server/usb/UsbDebuggingManager.java;

public class UsbDebuggingManager implements Runnable {
    private static final String TAG = "UsbDebuggingManager";
    private static final boolean DEBUG = false;

    private final String ADBD_SOCKET = "adbd";
    private final String ADB_DIRECTORY = "misc/adb";
    private final String ADB_KEYS_FILE = "adb_keys";
    private final int BUFFER_SIZE = 4096;

    private final Context mContext;
    private final Handler mHandler;
    private Thread mThread;
    private boolean mAdbEnabled = false;
    private String mFingerprints;
    private LocalSocket mSocket = null;
    private OutputStream mOutputStream = null;

    public UsbDebuggingManager(Context context) {
        mHandler = new UsbDebuggingHandler(FgThread.get().getLooper());
        mContext = context;
    }

2、这是一个Runnable线程,先看看里面有哪些功能,然后再看在哪里调用的;

3、首先构造函数中new了一个UsbDebuggingHandler消息对象;

    @Override
    public void run() {
        while (mAdbEnabled) {
            try {
                listenToSocket();
            } catch (Exception e) {
                /* Don't loop too fast if adbd dies, before init restarts it */
                SystemClock.sleep(1000);
            }
        }
    }

 

4、在run方法中,有一个监听Socket的方法-listenToSocket(),这个方法中有一个while循环,一直监听弹框之后用户点击的处理事件。

 

 

    private void listenToSocket() throws IOException {
        try {
            byte[] buffer = new byte[BUFFER_SIZE];
            LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
                                         LocalSocketAddress.Namespace.RESERVED);
            InputStream inputStream = null;

            mSocket = new LocalSocket();
            mSocket.connect(address);

            mOutputStream = mSocket.getOutputStream();
            inputStream = mSocket.getInputStream();

            while (true) {
                int count = inputStream.read(buffer);
                if (count < 0) {
                    break;
                }

                if (buffer[0] == 'P' && buffer[1] == 'K') {
                    String key = new String(Arrays.copyOfRange(buffer, 2, count));
                    Slog.d(TAG, "Received public key: " + key);
                    Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
                    msg.obj = key;
                    mHandler.sendMessage(msg);
                }
                else {
                    Slog.e(TAG, "Wrong message: " + (new String(Arrays.copyOfRange(buffer, 0, 2))));
                    break;
                }
            }
        } finally {
            closeSocket();
        }
    }

 

5、一直监听,当有p和k出现的时候,就开始弹出adb usb调试的授权弹框;发送消息,并有一个key的字符创从buffer中取出;消息ID:UsbDebuggingHandler.MESSAGE_ADB_CONFIRM

 

 

                case MESSAGE_ADB_CONFIRM: {
                    String key = (String)msg.obj;
                    String fingerprints = getFingerprints(key);
                    if ("".equals(fingerprints)) {
                        sendResponse("NO");
                        break;
                    }
                    mFingerprints = fingerprints;
                    startConfirmation(key, mFingerprints);
                    break;
                }

6、startConfirmation(key, mFingerprints);启动确认弹框,需要传入两个参数;

 

    private void startConfirmation(String key, String fingerprints) {
        String nameString = Resources.getSystem().getString(
                com.android.internal.R.string.config_customAdbPublicKeyConfirmationComponent);
        ComponentName componentName = ComponentName.unflattenFromString(nameString);
        if (startConfirmationActivity(componentName, key, fingerprints)
                || startConfirmationService(componentName, key, fingerprints)) {
            return;
        }
        Slog.e(TAG, "unable to start customAdbPublicKeyConfirmationComponent "
                + nameString + " as an Activity or a Service");
    }

7、开始启动弹框的activity,通过资源字符串获取启动的包名和类名:config_customAdbPublicKeyConfirmationComponent

字段,在frameworks/base/core/res/res/values/config.xml中有定义:

    <!-- Name of the activity or service that prompts the user to reject, accept, or whitelist
         an adb host's public key, when an unwhitelisted host connects to the local adbd.
         Can be customized for other product types -->
    <string name="config_customAdbPublicKeyConfirmationComponent"
            >com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity</string>

8、可以看出,这个弹框是系统的systemui应用弹出来的,这就好办了,直接查看这个类:UsbDebuggingActivity

9、frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java中有调用这个类

 

二、分析UsbDebuggingActivity类

public class UsbDebuggingActivity extends AlertActivity
                                  implements DialogInterface.OnClickListener {
    private static final String TAG = "UsbDebuggingActivity";

    private CheckBox mAlwaysAllow;
    private UsbDisconnectedReceiver mDisconnectedReceiver;
    private String mKey;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0) {
            mDisconnectedReceiver = new UsbDisconnectedReceiver(this);
        }

        Intent intent = getIntent();
        String fingerprints = intent.getStringExtra("fingerprints");
        mKey = intent.getStringExtra("key");

        if (fingerprints == null || mKey == null) {
            finish();
            return;
        }

        final AlertController.AlertParams ap = mAlertParams;
        ap.mTitle = getString(R.string.usb_debugging_title);
        ap.mMessage = getString(R.string.usb_debugging_message, fingerprints);
        ap.mPositiveButtonText = getString(android.R.string.ok);
        ap.mNegativeButtonText = getString(android.R.string.cancel);
        ap.mPositiveButtonListener = this;
        ap.mNegativeButtonListener = this;

        // add "always allow" checkbox
        LayoutInflater inflater = LayoutInflater.from(ap.mContext);
        View checkbox = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
        mAlwaysAllow = (CheckBox)checkbox.findViewById(com.android.internal.R.id.alwaysUse);
        mAlwaysAllow.setText(getString(R.string.usb_debugging_always));
        ap.mView = checkbox;

        setupAlert();
    }

1、通过一系列的判断,最终显示这个activity;

 

    private class UsbDisconnectedReceiver extends BroadcastReceiver {
        private final Activity mActivity;
        public UsbDisconnectedReceiver(Activity activity) {
            mActivity = activity;
        }

        @Override
        public void onReceive(Context content, Intent intent) {
            String action = intent.getAction();
            if (!UsbManager.ACTION_USB_STATE.equals(action)) {
                return;
            }
            boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
            if (!connected) {
                mActivity.finish();
            }
        }
    }

2、同时注册了一个广播,这个广播就监听USB的状态而已;

    @Override
    public void onClick(DialogInterface dialog, int which) {
        boolean allow = (which == AlertDialog.BUTTON_POSITIVE);
        boolean alwaysAllow = allow && mAlwaysAllow.isChecked();
        try {
            IBinder b = ServiceManager.getService(USB_SERVICE);
            IUsbManager service = IUsbManager.Stub.asInterface(b);
            if (allow) {
                service.allowUsbDebugging(alwaysAllow, mKey);
            } else {
                service.denyUsbDebugging();
            }
        } catch (Exception e) {
            Log.e(TAG, "Unable to notify Usb service", e);
        }
        finish();
    }

3、当点击确认的时候,需要走的流程,首先是获取IBinder对象,可以看出是通过Binder来进行授权的传递,授权需要有一个权限入门:mKey,同时这个类中也需要声明一个权限:

        <!-- started from UsbDebuggingManager -->
        <activity android:name=".usb.UsbDebuggingActivity"
            android:permission="android.permission.MANAGE_USB"
            android:theme="@style/Theme.SystemUI.Dialog.Alert"
            android:finishOnCloseSystemDialogs="true"
            android:excludeFromRecents="true">
        </activity>

 

4、这个权限是在SystemUI中声明的;

 

 

三、分析IUsbManager.aidl类和UsbService类

路径:frameworks/base/services/usb/java/com/android/server/usb/UsbService.java

路径:frameworks/base/core/java/android/hardware/usb/IUsbManager.aidl

 

IBinder b = ServiceManager.getService(USB_SERVICE);
IUsbManager service = IUsbManager.Stub.asInterface(b);
if (allow) {
    service.allowUsbDebugging(alwaysAllow, mKey);
} else {
    service.denyUsbDebugging();
}

1、此类是Binder类,进程之间相互调用的类,也就是说在server和client之间能够调用的类,这个类很重要,继续上面的分析,

可以看出IUsbManager.allowUsbDebugging();调用此方法,实际上,就是调用UsbService.java中的方法

 

/**
 * UsbService manages all USB related state, including both host and device support.
 * Host related events and calls are delegated to UsbHostManager, and device related
 * support is delegated to UsbDeviceManager.
 */
public class UsbService extends IUsbManager.Stub {

    public static class Lifecycle extends SystemService {
        private UsbService mUsbService;

        public Lifecycle(Context context) {
            super(context);
        }

        @Override
        public void onStart() {
            mUsbService = new UsbService(getContext());
            publishBinderService(Context.USB_SERVICE, mUsbService);
        }

2、类UsbService.java继承IUsbManager.Stub类,也就是IUsbManager.aidl,当调用IUsbManager.allowUsbDebugging()时,实际上调用的是UsbService.java中的代码如下:

    private static final String TAG = "UsbService";

    private final Context mContext;

    private UsbDeviceManager mDeviceManager;
    private UsbHostManager mHostManager;
		..................
    @Override
    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
        mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
    }

    @Override
    public void denyUsbDebugging() {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
        mDeviceManager.denyUsbDebugging();
    }

3、由代码看出,UsbService类,实质上是调用UsbDeviceManager和UsbHostManager类中的方法,至此,我们分析这个两个类即可,不必专门来分析UsbService了,

 

四、分析UsbDeviceManager.java类

1、继上面调用的方法:UsbDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);分析:

    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
        if (mDebuggingManager != null) {
            mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
        }
    }

    public void denyUsbDebugging() {
        if (mDebuggingManager != null) {
            mDebuggingManager.denyUsbDebugging();
        }
    }

2、这个方法又转调到了UsbDebuggingManager.allowUsbDebugging的方法;

    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_ALLOW);
        msg.arg1 = alwaysAllow ? 1 : 0;
        msg.obj = publicKey;
        mHandler.sendMessage(msg);
    }

    public void denyUsbDebugging() {
        mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_DENY);
    }

3、发送一个消息给handler;然后继续

                case MESSAGE_ADB_ALLOW: {
                    String key = (String)msg.obj;
                    String fingerprints = getFingerprints(key);

                    if (!fingerprints.equals(mFingerprints)) {
                        Slog.e(TAG, "Fingerprints do not match. Got "
                                + fingerprints + ", expected " + mFingerprints);
                        break;
                    }

                    if (msg.arg1 == 1) {
                        writeKey(key);
                    }

                    sendResponse("OK");
                    break;
                }

4、这里把key写入到文件中,然后发送一个ok字符给socket字节流中,就可以连接adb了,这个字节流是可以在有system权限的应用中监听的;

 

至此,简单的USB弹框授权就完成了!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值