11f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright/* 21f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * Copyright (C) 2015 The Android Open Source Project 31f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * 41f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * Licensed under the Apache License, Version 2.0 (the "License"); 51f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * you may not use this file except in compliance with the License. 61f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * You may obtain a copy of the License at 71f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * 81f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * http://www.apache.org/licenses/LICENSE-2.0 91f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * 101f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * Unless required by applicable law or agreed to in writing, software 111f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * distributed under the License is distributed on an "AS IS" BASIS, 121f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * See the License for the specific language governing permissions and 141f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright * limitations under the License. 151f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright */ 161f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 171f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightpackage com.android.commands.hid; 181f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 191f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightimport android.util.JsonReader; 201f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightimport android.util.JsonToken; 211f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightimport android.util.Log; 221f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 231f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightimport java.io.InputStreamReader; 241f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightimport java.io.IOException; 251f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightimport java.util.ArrayList; 261f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightimport java.util.Arrays; 271f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 281f2c7688c1f673790d61645632ae5e1838f021a4Michael Wrightpublic class Event { 291f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private static final String TAG = "HidEvent"; 301f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 311f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public static final String COMMAND_REGISTER = "register"; 321f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public static final String COMMAND_DELAY = "delay"; 331f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public static final String COMMAND_REPORT = "report"; 341f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 351f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private int mId; 361f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private String mCommand; 371f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private String mName; 381f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private byte[] mDescriptor; 391f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private int mVid; 401f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private int mPid; 411f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private byte[] mReport; 421f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private int mDuration; 431f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 441f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public int getId() { 451f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mId; 461f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 471f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 481f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public String getCommand() { 491f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mCommand; 501f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 511f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 521f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public String getName() { 531f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mName; 541f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 551f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 561f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public byte[] getDescriptor() { 571f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mDescriptor; 581f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 591f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 601f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public int getVendorId() { 611f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mVid; 621f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 631f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 641f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public int getProductId() { 651f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mPid; 661f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 671f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 681f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public byte[] getReport() { 691f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mReport; 701f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 711f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 721f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public int getDuration() { 731f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mDuration; 741f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 751f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 761f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public String toString() { 771f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return "Event{id=" + mId 781f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright + ", command=" + String.valueOf(mCommand) 791f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright + ", name=" + String.valueOf(mName) 801f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright + ", descriptor=" + Arrays.toString(mDescriptor) 811f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright + ", vid=" + mVid 821f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright + ", pid=" + mPid 831f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright + ", report=" + Arrays.toString(mReport) 841f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright + ", duration=" + mDuration 851f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright + "}"; 861f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 871f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 881f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private static class Builder { 891f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private Event mEvent; 901f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 911f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public Builder() { 921f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent = new Event(); 931f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 941f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 951f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public void setId(int id) { 961f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent.mId = id; 971f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 981f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 991f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private void setCommand(String command) { 1001f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent.mCommand = command; 1011f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1021f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1031f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public void setName(String name) { 1041f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent.mName = name; 1051f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1061f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1071f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public void setDescriptor(byte[] descriptor) { 1081f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent.mDescriptor = descriptor; 1091f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1101f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1111f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public void setReport(byte[] report) { 1121f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent.mReport = report; 1131f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1141f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1151f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public void setVid(int vid) { 1161f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent.mVid = vid; 1171f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1181f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1191f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public void setPid(int pid) { 1201f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent.mPid = pid; 1211f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1221f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1231f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public void setDuration(int duration) { 1241f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mEvent.mDuration = duration; 1251f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1261f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1271f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public Event build() { 1281f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright if (mEvent.mId == -1) { 1291f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright throw new IllegalStateException("No event id"); 1301f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } else if (mEvent.mCommand == null) { 1311f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright throw new IllegalStateException("Event does not contain a command"); 1321f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1331f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright if (COMMAND_REGISTER.equals(mEvent.mCommand)) { 1341f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright if (mEvent.mDescriptor == null) { 1351f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright throw new IllegalStateException("Device registration is missing descriptor"); 1361f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1371f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } else if (COMMAND_DELAY.equals(mEvent.mCommand)) { 1381f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright if (mEvent.mDuration <= 0) { 1391f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright throw new IllegalStateException("Delay has missing or invalid duration"); 1401f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1411f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } else if (COMMAND_REPORT.equals(mEvent.mCommand)) { 1421f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright if (mEvent.mReport == null) { 1431f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright throw new IllegalStateException("Report command is missing report data"); 1441f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1451f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1461f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return mEvent; 1471f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1481f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1491f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1501f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public static class Reader { 1511f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private JsonReader mReader; 1521f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1531f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public Reader(InputStreamReader in) { 1541f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader = new JsonReader(in); 1551f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.setLenient(true); 1561f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1571f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 1581f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright public Event getNextEvent() throws IOException { 1591f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright Event e = null; 1601f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright while (e == null && mReader.peek() != JsonToken.END_DOCUMENT) { 1611f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright Event.Builder eb = new Event.Builder(); 1621f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright try { 1631f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.beginObject(); 1641f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright while (mReader.hasNext()) { 1651f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright String name = mReader.nextName(); 1661f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright switch (name) { 1671f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright case "id": 1681f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright eb.setId(readInt()); 1691f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright break; 1701f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright case "command": 1711f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright eb.setCommand(mReader.nextString()); 1721f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright break; 1731f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright case "descriptor": 1741f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright eb.setDescriptor(readData()); 1751f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright break; 1761f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright case "name": 1771f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright eb.setName(mReader.nextString()); 1781f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright break; 1791f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright case "vid": 1801f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright eb.setVid(readInt()); 1811f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright break; 1821f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright case "pid": 1831f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright eb.setPid(readInt()); 1841f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright break; 1851f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright case "report": 1861f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright eb.setReport(readData()); 1871f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright break; 1881f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright case "duration": 1891f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright eb.setDuration(readInt()); 1901f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright break; 1911f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright default: 1921f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.skipValue(); 1931f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1941f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 1951f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.endObject(); 1961f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } catch (IllegalStateException ex) { 1971f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright error("Error reading in object, ignoring.", ex); 1981f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright consumeRemainingElements(); 1991f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.endObject(); 2001f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright continue; 2011f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2021f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright e = eb.build(); 2031f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2041f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 2051f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return e; 2061f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2071f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 2081f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private byte[] readData() throws IOException { 2091f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright ArrayList<Integer> data = new ArrayList<Integer>(); 2101f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright try { 2111f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.beginArray(); 2121f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright while (mReader.hasNext()) { 2131f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright data.add(Integer.decode(mReader.nextString())); 2141f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2151f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.endArray(); 2161f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } catch (IllegalStateException|NumberFormatException e) { 2171f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright consumeRemainingElements(); 2181f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.endArray(); 2191f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright throw new IllegalStateException("Encountered malformed data.", e); 2201f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2211f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright byte[] rawData = new byte[data.size()]; 2221f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright for (int i = 0; i < data.size(); i++) { 2231f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright int d = data.get(i); 2241f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright if ((d & 0xFF) != d) { 2251f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright throw new IllegalStateException("Invalid data, all values must be byte-sized"); 2261f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2271f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright rawData[i] = (byte)d; 2281f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2291f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return rawData; 2301f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2311f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 2321f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private int readInt() throws IOException { 2331f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright String val = mReader.nextString(); 2341f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright return Integer.decode(val); 2351f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2361f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 2371f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private void consumeRemainingElements() throws IOException { 2381f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright while (mReader.hasNext()) { 2391f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright mReader.skipValue(); 2401f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2411f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2421f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2431f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 2441f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private static void error(String msg) { 2451f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright error(msg, null); 2461f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2471f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright 2481f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright private static void error(String msg, Exception e) { 2491f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright System.out.println(msg); 2501f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright Log.e(TAG, msg); 2511f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright if (e != null) { 2521f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright Log.e(TAG, Log.getStackTraceString(e)); 2531f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2541f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright } 2551f2c7688c1f673790d61645632ae5e1838f021a4Michael Wright} 256