14e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby/*
24e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * Copyright (C) 2012 The Android Open Source Project
34e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby *
44e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * Licensed under the Apache License, Version 2.0 (the "License");
54e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * you may not use this file except in compliance with the License.
64e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * You may obtain a copy of the License at
74e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby *
84e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby *      http://www.apache.org/licenses/LICENSE-2.0
94e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby *
104e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * Unless required by applicable law or agreed to in writing, software
114e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * distributed under the License is distributed on an "AS IS" BASIS,
124e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * See the License for the specific language governing permissions an
144e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby * limitations under the License.
154e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby */
164e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
174e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobypackage com.android.server.usb;
184e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
19ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chenimport android.app.ActivityManager;
204e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.content.ActivityNotFoundException;
21f10d0399bf5f519dff414a9d195a0eaacb37f9b7Aaron Whyteimport android.content.ComponentName;
224e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.content.Context;
234e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.content.Intent;
24d1931ffc075f73d043616b7446f14a653609782eAaron Whyteimport android.content.pm.PackageManager;
2505d58afddb1bbfa893354c1cb331bd69c9d2cb6fXiaohui Chenimport android.content.pm.UserInfo;
26f10d0399bf5f519dff414a9d195a0eaacb37f9b7Aaron Whyteimport android.content.res.Resources;
274e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.net.LocalSocket;
284e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.net.LocalSocketAddress;
294e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.os.Environment;
304e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.os.FileUtils;
31ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chenimport android.os.Handler;
324e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.os.Looper;
334e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.os.Message;
344e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.os.SystemClock;
35b43d3cff67b831db3b7e9fb834de66e4f9d2bc16Craig Mautnerimport android.os.SystemProperties;
36b43d3cff67b831db3b7e9fb834de66e4f9d2bc16Craig Mautnerimport android.os.UserHandle;
37ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chenimport android.os.UserManager;
384e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport android.util.Base64;
39ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chenimport android.util.Slog;
40f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani
41ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chenimport com.android.internal.R;
422dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brownimport com.android.internal.util.IndentingPrintWriter;
438d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackbornimport com.android.server.FgThread;
444e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
454e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.io.File;
464e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.io.FileDescriptor;
474e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.io.FileOutputStream;
484e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.io.IOException;
494e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.io.InputStream;
504e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.io.OutputStream;
514e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.io.PrintWriter;
524e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.security.MessageDigest;
534e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Gobyimport java.util.Arrays;
544e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
55f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasanipublic class UsbDebuggingManager {
564e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private static final String TAG = "UsbDebuggingManager";
574e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private static final boolean DEBUG = false;
584e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
594e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private final String ADBD_SOCKET = "adbd";
604e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private final String ADB_DIRECTORY = "misc/adb";
614e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private final String ADB_KEYS_FILE = "adb_keys";
624e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private final int BUFFER_SIZE = 4096;
634e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
644e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private final Context mContext;
654e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private final Handler mHandler;
66f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani    private UsbDebuggingThread mThread;
674e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private boolean mAdbEnabled = false;
684e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private String mFingerprints;
694e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
704e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public UsbDebuggingManager(Context context) {
718d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackborn        mHandler = new UsbDebuggingHandler(FgThread.get().getLooper());
724e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mContext = context;
734e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
744e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
75f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani    class UsbDebuggingThread extends Thread {
76f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        private boolean mStopped;
77f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        private LocalSocket mSocket;
78f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        private OutputStream mOutputStream;
79f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        private InputStream mInputStream;
804e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
81f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        UsbDebuggingThread() {
82f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            super(TAG);
83f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        }
844e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
85f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        @Override
86f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        public void run() {
87f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            if (DEBUG) Slog.d(TAG, "Entering thread");
884e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            while (true) {
89f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                synchronized (this) {
90f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    if (mStopped) {
91f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        if (DEBUG) Slog.d(TAG, "Exiting thread");
92f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        return;
93f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    }
94f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    try {
95f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        openSocketLocked();
96f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    } catch (Exception e) {
97f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        /* Don't loop too fast if adbd dies, before init restarts it */
98f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        SystemClock.sleep(1000);
99f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    }
1004e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                }
101f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                try {
102f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    listenToSocket();
103f4a8df4c7ee8d6a402e26339514cd73aba613105Amith Yamasani                } catch (Exception e) {
104f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    /* Don't loop too fast if adbd dies, before init restarts it */
105f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    SystemClock.sleep(1000);
1064e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                }
1074e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            }
1084e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
1094e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
110f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        private void openSocketLocked() throws IOException {
1114e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            try {
112f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
113f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        LocalSocketAddress.Namespace.RESERVED);
114f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                mInputStream = null;
115f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani
116f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                if (DEBUG) Slog.d(TAG, "Creating socket");
117f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                mSocket = new LocalSocket();
118f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                mSocket.connect(address);
119f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani
120f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                mOutputStream = mSocket.getOutputStream();
121f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                mInputStream = mSocket.getInputStream();
122f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            } catch (IOException ioe) {
123f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                closeSocketLocked();
124f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                throw ioe;
1254e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            }
1264e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
1274e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
128f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        private void listenToSocket() throws IOException {
129f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            try {
130f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                byte[] buffer = new byte[BUFFER_SIZE];
131f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                while (true) {
132f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    int count = mInputStream.read(buffer);
133f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    if (count < 0) {
134f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        break;
135f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    }
1364e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
137f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    if (buffer[0] == 'P' && buffer[1] == 'K') {
138f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        String key = new String(Arrays.copyOfRange(buffer, 2, count));
139f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        Slog.d(TAG, "Received public key: " + key);
140f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
141f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        msg.obj = key;
142f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        mHandler.sendMessage(msg);
143f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    } else {
144f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        Slog.e(TAG, "Wrong message: "
145f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                                + (new String(Arrays.copyOfRange(buffer, 0, 2))));
146f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        break;
147f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    }
148f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                }
149f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            } finally {
150f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                synchronized (this) {
151f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    closeSocketLocked();
152f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                }
153f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            }
1544e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
1554e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
156f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        private void closeSocketLocked() {
157f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            if (DEBUG) Slog.d(TAG, "Closing socket");
158f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            try {
159f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                if (mOutputStream != null) {
160f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    mOutputStream.close();
161f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    mOutputStream = null;
162f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                }
163f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            } catch (IOException e) {
164f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                Slog.e(TAG, "Failed closing output stream: " + e);
165f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            }
166f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani
1674e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            try {
168f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                if (mSocket != null) {
169f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    mSocket.close();
170f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    mSocket = null;
171f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                }
172f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            } catch (IOException ex) {
173f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                Slog.e(TAG, "Failed closing socket: " + ex);
1744e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            }
175f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        }
176f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani
177f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        /** Call to stop listening on the socket and exit the thread. */
178f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        void stopListening() {
179f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            synchronized (this) {
180f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                mStopped = true;
181f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                closeSocketLocked();
182f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            }
183f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        }
184f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani
185f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani        void sendResponse(String msg) {
186f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani            synchronized (this) {
187f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                if (!mStopped && mOutputStream != null) {
188f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    try {
189f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        mOutputStream.write(msg.getBytes());
190f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    }
191f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    catch (IOException ex) {
192f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        Slog.e(TAG, "Failed to write response:", ex);
193f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    }
194f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                }
1954e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            }
1964e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
1974e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
1984e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
1994e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    class UsbDebuggingHandler extends Handler {
2004e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        private static final int MESSAGE_ADB_ENABLED = 1;
2014e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        private static final int MESSAGE_ADB_DISABLED = 2;
2024e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        private static final int MESSAGE_ADB_ALLOW = 3;
2034e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        private static final int MESSAGE_ADB_DENY = 4;
2044e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        private static final int MESSAGE_ADB_CONFIRM = 5;
205cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        private static final int MESSAGE_ADB_CLEAR = 6;
2064e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2074e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        public UsbDebuggingHandler(Looper looper) {
2084e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            super(looper);
2094e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
2104e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2114e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        public void handleMessage(Message msg) {
2124e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            switch (msg.what) {
2134e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                case MESSAGE_ADB_ENABLED:
2144e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    if (mAdbEnabled)
2154e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                        break;
2164e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2174e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    mAdbEnabled = true;
2184e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
219f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    mThread = new UsbDebuggingThread();
2204e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    mThread.start();
2214e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2224e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    break;
2234e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2244e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                case MESSAGE_ADB_DISABLED:
2254e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    if (!mAdbEnabled)
2264e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                        break;
2274e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2284e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    mAdbEnabled = false;
2294e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
230f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    if (mThread != null) {
231f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        mThread.stopListening();
232f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        mThread = null;
2334e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    }
2344e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
23537ce5c5d5e8216f02230aeb89b147c0395e18329Benoit Goby                    break;
2364e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2374e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                case MESSAGE_ADB_ALLOW: {
2384e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    String key = (String)msg.obj;
2394e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    String fingerprints = getFingerprints(key);
2404e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2414e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    if (!fingerprints.equals(mFingerprints)) {
2424e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                        Slog.e(TAG, "Fingerprints do not match. Got "
2434e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                                + fingerprints + ", expected " + mFingerprints);
2444e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                        break;
2454e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    }
2464e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2474e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    if (msg.arg1 == 1) {
2484e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                        writeKey(key);
2494e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    }
2504e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
251f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    if (mThread != null) {
252f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        mThread.sendResponse("OK");
253f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    }
2544e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    break;
2554e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                }
2564e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2574e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                case MESSAGE_ADB_DENY:
258f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    if (mThread != null) {
259f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        mThread.sendResponse("NO");
260f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                    }
2614e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    break;
2624e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2634e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                case MESSAGE_ADB_CONFIRM: {
264b43d3cff67b831db3b7e9fb834de66e4f9d2bc16Craig Mautner                    if ("trigger_restart_min_framework".equals(
265b43d3cff67b831db3b7e9fb834de66e4f9d2bc16Craig Mautner                            SystemProperties.get("vold.decrypt"))) {
266b43d3cff67b831db3b7e9fb834de66e4f9d2bc16Craig Mautner                        Slog.d(TAG, "Deferring adb confirmation until after vold decrypt");
267f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        if (mThread != null) {
268f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                            mThread.sendResponse("NO");
269f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        }
270b43d3cff67b831db3b7e9fb834de66e4f9d2bc16Craig Mautner                        break;
271b43d3cff67b831db3b7e9fb834de66e4f9d2bc16Craig Mautner                    }
2724e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    String key = (String)msg.obj;
273451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich                    String fingerprints = getFingerprints(key);
274451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich                    if ("".equals(fingerprints)) {
275f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        if (mThread != null) {
276f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                            mThread.sendResponse("NO");
277f6197e8fa25d7a411a08ca01f9af8f6278ef97d6Amith Yamasani                        }
278451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich                        break;
279451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich                    }
280451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich                    mFingerprints = fingerprints;
281d1931ffc075f73d043616b7446f14a653609782eAaron Whyte                    startConfirmation(key, mFingerprints);
2824e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    break;
2834e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                }
284cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby
285cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby                case MESSAGE_ADB_CLEAR:
286cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby                    deleteKeyFile();
287cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby                    break;
2884e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            }
2894e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
2904e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
2914e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
2924e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    private String getFingerprints(String key) {
2934e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        String hex = "0123456789ABCDEF";
2944e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        StringBuilder sb = new StringBuilder();
2954e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        MessageDigest digester;
2964e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
297451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich        if (key == null) {
298451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich            return "";
299451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich        }
300451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich
3014e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        try {
3024e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            digester = MessageDigest.getInstance("MD5");
3034e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        } catch (Exception ex) {
304451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich            Slog.e(TAG, "Error getting digester", ex);
3054e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            return "";
3064e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
3074e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
3084e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        byte[] base64_data = key.split("\\s+")[0].getBytes();
309451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich        byte[] digest;
310451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich        try {
311451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich            digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT));
312451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich        } catch (IllegalArgumentException e) {
313451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich            Slog.e(TAG, "error doing base64 decoding", e);
314451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich            return "";
315451a6f8f9a5e629a94b3cb75eb2d8576caea5471Nick Kralevich        }
3164e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        for (int i = 0; i < digest.length; i++) {
3174e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            sb.append(hex.charAt((digest[i] >> 4) & 0xf));
3184e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            sb.append(hex.charAt(digest[i] & 0xf));
3194e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            if (i < digest.length - 1)
3204e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                sb.append(":");
3214e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
3224e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        return sb.toString();
3234e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
3244e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
325d1931ffc075f73d043616b7446f14a653609782eAaron Whyte    private void startConfirmation(String key, String fingerprints) {
326ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen        int currentUserId = ActivityManager.getCurrentUser();
32705d58afddb1bbfa893354c1cb331bd69c9d2cb6fXiaohui Chen        UserInfo userInfo = UserManager.get(mContext).getUserInfo(currentUserId);
328ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen        String componentString;
32905d58afddb1bbfa893354c1cb331bd69c9d2cb6fXiaohui Chen        if (userInfo.isAdmin()) {
330ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen            componentString = Resources.getSystem().getString(
331ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen                    com.android.internal.R.string.config_customAdbPublicKeyConfirmationComponent);
332ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen        } else {
33305d58afddb1bbfa893354c1cb331bd69c9d2cb6fXiaohui Chen            // If the current foreground user is not the admin user we send a different
334ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen            // notification specific to secondary users.
335ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen            componentString = Resources.getSystem().getString(
336ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen                    R.string.config_customAdbPublicKeyConfirmationSecondaryUserComponent);
337ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen        }
338ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen        ComponentName componentName = ComponentName.unflattenFromString(componentString);
33905d58afddb1bbfa893354c1cb331bd69c9d2cb6fXiaohui Chen        if (startConfirmationActivity(componentName, userInfo.getUserHandle(), key, fingerprints)
34005d58afddb1bbfa893354c1cb331bd69c9d2cb6fXiaohui Chen                || startConfirmationService(componentName, userInfo.getUserHandle(),
34105d58afddb1bbfa893354c1cb331bd69c9d2cb6fXiaohui Chen                        key, fingerprints)) {
342d1931ffc075f73d043616b7446f14a653609782eAaron Whyte            return;
343d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        }
344ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen        Slog.e(TAG, "unable to start customAdbPublicKeyConfirmation[SecondaryUser]Component "
345ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen                + componentString + " as an Activity or a Service");
346d1931ffc075f73d043616b7446f14a653609782eAaron Whyte    }
347f10d0399bf5f519dff414a9d195a0eaacb37f9b7Aaron Whyte
348d1931ffc075f73d043616b7446f14a653609782eAaron Whyte    /**
349d1931ffc075f73d043616b7446f14a653609782eAaron Whyte     * @returns true if the componentName led to an Activity that was started.
350d1931ffc075f73d043616b7446f14a653609782eAaron Whyte     */
351ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen    private boolean startConfirmationActivity(ComponentName componentName, UserHandle userHandle,
352ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen            String key, String fingerprints) {
353d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        PackageManager packageManager = mContext.getPackageManager();
354d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        Intent intent = createConfirmationIntent(componentName, key, fingerprints);
355f10d0399bf5f519dff414a9d195a0eaacb37f9b7Aaron Whyte        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
356d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
357d1931ffc075f73d043616b7446f14a653609782eAaron Whyte            try {
358ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen                mContext.startActivityAsUser(intent, userHandle);
359d1931ffc075f73d043616b7446f14a653609782eAaron Whyte                return true;
360d1931ffc075f73d043616b7446f14a653609782eAaron Whyte            } catch (ActivityNotFoundException e) {
361d1931ffc075f73d043616b7446f14a653609782eAaron Whyte                Slog.e(TAG, "unable to start adb whitelist activity: " + componentName, e);
362d1931ffc075f73d043616b7446f14a653609782eAaron Whyte            }
363d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        }
364d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        return false;
365d1931ffc075f73d043616b7446f14a653609782eAaron Whyte    }
366d1931ffc075f73d043616b7446f14a653609782eAaron Whyte
367d1931ffc075f73d043616b7446f14a653609782eAaron Whyte    /**
368d1931ffc075f73d043616b7446f14a653609782eAaron Whyte     * @returns true if the componentName led to a Service that was started.
369d1931ffc075f73d043616b7446f14a653609782eAaron Whyte     */
370ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen    private boolean startConfirmationService(ComponentName componentName, UserHandle userHandle,
371ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen            String key, String fingerprints) {
372d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        Intent intent = createConfirmationIntent(componentName, key, fingerprints);
3734e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        try {
374ffcfe3411ff6ccaa35c2873151e31c879506daddXiaohui Chen            if (mContext.startServiceAsUser(intent, userHandle) != null) {
375d1931ffc075f73d043616b7446f14a653609782eAaron Whyte                return true;
376d1931ffc075f73d043616b7446f14a653609782eAaron Whyte            }
377d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        } catch (SecurityException e) {
378d1931ffc075f73d043616b7446f14a653609782eAaron Whyte            Slog.e(TAG, "unable to start adb whitelist service: " + componentName, e);
3794e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
380d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        return false;
381d1931ffc075f73d043616b7446f14a653609782eAaron Whyte    }
382d1931ffc075f73d043616b7446f14a653609782eAaron Whyte
383d1931ffc075f73d043616b7446f14a653609782eAaron Whyte    private Intent createConfirmationIntent(ComponentName componentName, String key,
384d1931ffc075f73d043616b7446f14a653609782eAaron Whyte            String fingerprints) {
385d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        Intent intent = new Intent();
386d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        intent.setClassName(componentName.getPackageName(), componentName.getClassName());
387d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        intent.putExtra("key", key);
388d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        intent.putExtra("fingerprints", fingerprints);
389d1931ffc075f73d043616b7446f14a653609782eAaron Whyte        return intent;
3904e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
3914e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
392cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    private File getUserKeyFile() {
3934e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        File dataDir = Environment.getDataDirectory();
3944e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        File adbDir = new File(dataDir, ADB_DIRECTORY);
3954e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
3964e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        if (!adbDir.exists()) {
3974e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            Slog.e(TAG, "ADB data directory does not exist");
398cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby            return null;
3994e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
4004e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
401cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        return new File(adbDir, ADB_KEYS_FILE);
402cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    }
403cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby
404cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    private void writeKey(String key) {
4054e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        try {
406cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby            File keyFile = getUserKeyFile();
407cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby
408cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby            if (keyFile == null) {
409cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby                return;
410cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby            }
4114e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
4124e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            if (!keyFile.exists()) {
4134e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                keyFile.createNewFile();
4144e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                FileUtils.setPermissions(keyFile.toString(),
4154e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    FileUtils.S_IRUSR | FileUtils.S_IWUSR |
4164e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                    FileUtils.S_IRGRP, -1, -1);
4174e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            }
4184e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
4194e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            FileOutputStream fo = new FileOutputStream(keyFile, true);
4204e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            fo.write(key.getBytes());
4214e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            fo.write('\n');
4224e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            fo.close();
4234e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
4244e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        catch (IOException ex) {
4254e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            Slog.e(TAG, "Error writing key:" + ex);
4264e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
4274e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
4284e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
429cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    private void deleteKeyFile() {
430cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        File keyFile = getUserKeyFile();
431cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        if (keyFile != null) {
432cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby            keyFile.delete();
433cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        }
434cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    }
4354e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
4364e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void setAdbEnabled(boolean enabled) {
4374e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mHandler.sendEmptyMessage(enabled ? UsbDebuggingHandler.MESSAGE_ADB_ENABLED
4384e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby                                          : UsbDebuggingHandler.MESSAGE_ADB_DISABLED);
4394e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
4404e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
4414e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
4424e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_ALLOW);
4434e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        msg.arg1 = alwaysAllow ? 1 : 0;
4444e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        msg.obj = publicKey;
4454e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mHandler.sendMessage(msg);
4464e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
4474e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
4484e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    public void denyUsbDebugging() {
4494e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_DENY);
4504e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
4514e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
452cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    public void clearUsbDebuggingKeys() {
453cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby        mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_CLEAR);
454cd7a17c645761ac0b64c75346b159dd30cbcb01cBenoit Goby    }
4554e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby
4562dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown    public void dump(IndentingPrintWriter pw) {
4572dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown        pw.println("USB Debugging State:");
4582dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown        pw.println("  Connected to adbd: " + (mThread != null));
4592dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown        pw.println("  Last key received: " + mFingerprints);
4602dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown        pw.println("  User keys:");
4614e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        try {
4624e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            pw.println(FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null));
4634e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        } catch (IOException e) {
4644e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            pw.println("IOException: " + e);
4654e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
4662dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown        pw.println("  System keys:");
4674e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        try {
4684e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            pw.println(FileUtils.readTextFile(new File("/adb_keys"), 0, null));
4694e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        } catch (IOException e) {
4704e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby            pw.println("IOException: " + e);
4714e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby        }
4724e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby    }
4734e68bd420b6cfdbeadb5e69aa6448665b2da762bBenoit Goby}
474