10d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamypackage com.android.test.hierarchyviewer; 20d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 30d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamyimport java.nio.ByteBuffer; 40d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamyimport java.nio.charset.Charset; 50d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamyimport java.util.HashMap; 60d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamyimport java.util.Map; 70d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 80d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamypublic class Decoder { 90d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy // Prefixes for simple primitives. These match the JNI definitions. 100d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_BOOLEAN = 'Z'; 110d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_BYTE = 'B'; 120d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_SHORT = 'S'; 130d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_INT = 'I'; 140d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_LONG = 'J'; 150d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_FLOAT = 'F'; 160d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_DOUBLE = 'D'; 170d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 180d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy // Prefixes for some commonly used objects 190d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_STRING = 'R'; 200d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 210d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final byte SIG_MAP = 'M'; // a map with an short key 220d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static final short SIG_END_MAP = 0; 230d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 240d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy private final ByteBuffer mBuf; 250d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 260d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public Decoder(byte[] buf) { 270d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy this(ByteBuffer.wrap(buf)); 280d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 290d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 300d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public Decoder(ByteBuffer buf) { 310d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy mBuf = buf; 320d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 330d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 340d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public boolean hasRemaining() { 350d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return mBuf.hasRemaining(); 360d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 370d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 380d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public Object readObject() { 390d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy byte sig = mBuf.get(); 400d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 410d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy switch (sig) { 420d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_BOOLEAN: 430d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return mBuf.get() == 0 ? Boolean.FALSE : Boolean.TRUE; 440d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_BYTE: 450d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return mBuf.get(); 460d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_SHORT: 470d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return mBuf.getShort(); 480d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_INT: 490d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return mBuf.getInt(); 500d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_LONG: 510d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return mBuf.getLong(); 520d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_FLOAT: 530d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return mBuf.getFloat(); 540d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_DOUBLE: 550d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return mBuf.getDouble(); 560d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_STRING: 570d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return readString(); 580d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy case SIG_MAP: 590d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return readMap(); 600d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy default: 610d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy throw new DecoderException(sig, mBuf.position() - 1); 620d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 630d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 640d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 650d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy private String readString() { 660d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy short len = mBuf.getShort(); 670d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy byte[] b = new byte[len]; 680d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy mBuf.get(b, 0, len); 690d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return new String(b, Charset.forName("utf-8")); 700d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 710d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 720d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy private Map<Short, Object> readMap() { 730d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy Map<Short, Object> m = new HashMap<Short, Object>(); 740d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 750d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy while (true) { 760d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy Object o = readObject(); 770d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy if (!(o instanceof Short)) { 780d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy throw new DecoderException("Expected short key, got " + o.getClass()); 790d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 800d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 810d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy Short key = (Short)o; 820d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy if (key == SIG_END_MAP) { 830d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy break; 840d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 850d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 860d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy m.put(key, readObject()); 870d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 880d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 890d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy return m; 900d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 910d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 920d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public static class DecoderException extends RuntimeException { 930d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public DecoderException(byte seen, int pos) { 940d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy super(String.format("Unexpected byte %c seen at position %d", (char)seen, pos)); 950d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 960d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy 970d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy public DecoderException(String msg) { 980d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy super(msg); 990d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 1000d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy } 1010d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy} 102