1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.apache.harmony.dalvik.ddmc;
18 
19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20 
21 import android.annotation.SystemApi;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 
26 /**
27  * Handle a chunk of data sent from a DDM server.
28  *
29  * To handle a chunk type, sub-class {@link ChunkHandler} and register your class
30  * with {@link DdmServer}.
31  *
32  * @hide
33  */
34 @SystemApi(client = MODULE_LIBRARIES)
35 public abstract class ChunkHandler {
36 
37     /**
38      * Byte order of the data in the chunk.
39      *
40      * @hide
41      */
42     @UnsupportedAppUsage
43     @SystemApi(client = MODULE_LIBRARIES)
44     public static final ByteOrder CHUNK_ORDER = ByteOrder.BIG_ENDIAN;
45 
46     /**
47      * @hide
48      */
49     public static final int CHUNK_FAIL = type("FAIL");
50 
51     /**
52      * Constructs chunk handler.
53      *
54      * @hide
55      */
56     @SystemApi(client = MODULE_LIBRARIES)
ChunkHandler()57     public ChunkHandler() {}
58 
59     /**
60      * Called when the DDM server connects.  The handler is allowed to
61      * send messages to the server.
62      *
63      * @hide
64      */
65     @SystemApi(client = MODULE_LIBRARIES)
onConnected()66     public abstract void onConnected();
67 
68     /**
69      * Called when the DDM server disconnects.  Can be used to disable
70      * periodic transmissions or clean up saved state.
71      *
72      * @hide
73      */
74     @SystemApi(client = MODULE_LIBRARIES)
onDisconnected()75     public abstract void onDisconnected();
76 
77     /**
78      * Handle a single chunk of data.  {@code request} includes the type and
79      * the chunk payload.
80      *
81      * Returns a response in a {@link Chunk}.
82      *
83      * @param request chunk type and payload
84      * @return        {@link Chunk} with response
85      *
86      * @hide
87      */
88     @SystemApi(client = MODULE_LIBRARIES)
handleChunk(Chunk request)89     public abstract Chunk handleChunk(Chunk request);
90 
91     /**
92      * Create a FAIL chunk.  The {@link #handleChunk(Chunk)} methods can use this to
93      * return an error message when they are not able to process a chunk.
94      *
95      * @param errorCode arbitrary number to distinguish error
96      * @param msg       error message
97      * @return          {@link Chunk} with response
98      *
99      * @hide
100      */
101     @SystemApi(client = MODULE_LIBRARIES)
createFailChunk(int errorCode, String msg)102     public static Chunk createFailChunk(int errorCode, String msg) {
103         if (msg == null)
104             msg = "";
105 
106         ByteBuffer out = ByteBuffer.allocate(8 + msg.length() * 2);
107         out.order(ChunkHandler.CHUNK_ORDER);
108         out.putInt(errorCode);
109         out.putInt(msg.length());
110         final int len = msg.length();
111         for (int i = 0; i < len; i++) {
112             out.putChar(msg.charAt(i));
113         }
114 
115         return new Chunk(CHUNK_FAIL, out);
116     }
117 
118     /**
119      * Utility function to wrap a {@link ByteBuffer} around a {@link Chunk}.
120      *
121      * @param request chunk to be wrapped
122      * @return        {@link ByteBuffer} wrapping data from the given chunk
123      *
124      * @hide
125      */
126     @SystemApi(client = MODULE_LIBRARIES)
wrapChunk(Chunk request)127     public static ByteBuffer wrapChunk(Chunk request) {
128         ByteBuffer in;
129 
130         in = ByteBuffer.wrap(request.data, request.offset, request.length);
131         in.order(CHUNK_ORDER);
132         return in;
133     }
134 
135     /**
136      * Convert a 4-character string to a 32-bit type.
137      *
138      * @hide
139      */
140     @SystemApi(client = MODULE_LIBRARIES)
type(String typeName)141     public static int type(String typeName) {
142         if (typeName.length() != 4) {
143             throw new IllegalArgumentException("Bad type name: " + typeName);
144         }
145         int result = 0;
146         for (int i = 0; i < 4; ++i) {
147             result = ((result << 8) | (typeName.charAt(i) & 0xff));
148         }
149         return result;
150     }
151 
152     /**
153      * Convert an integer type to a 4-character string.
154      *
155      * @hide
156      */
157     @SystemApi(client = MODULE_LIBRARIES)
name(int type)158     public static String name(int type)
159     {
160         char[] ascii = new char[4];
161 
162         ascii[0] = (char) ((type >> 24) & 0xff);
163         ascii[1] = (char) ((type >> 16) & 0xff);
164         ascii[2] = (char) ((type >> 8) & 0xff);
165         ascii[3] = (char) (type & 0xff);
166 
167         return new String(ascii);
168     }
169 }
170