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 android.core;
18 
19 import java.util.ArrayList;
20 import java.util.Map;
21 
22 import org.apache.http.protocol.HTTP;
23 import android.util.Log;
24 import android.net.http.*;
25 
26 /**
27  * Implements EventHandler and provides test functionality to validate
28  * responses to requests from the test server
29  */
30 public class TestEventHandler implements EventHandler {
31 
32     /**
33      * Status variables
34      */
35     private int majorVersion = -1;
36     private int minorVersion = -1;
37     private int responseCode = -1;
38     private String reasonPhrase;
39 
40     /* List of headers received */
41     private Map<String, String> headerMap;
42 
43     /* Used to sync low level delayed requests */
44     public static final Object syncObj = new Object();
45 
46     /* Indicates whether the low level request testing is in operation */
47     private boolean useLowLevel = false;
48 
49     /* Indicates whether responses should be automatically generated or
50      * delayed
51      */
52     private boolean delayResponse = false;
53 
54     /* Test method expectation identifiers */
55     public final static int TEST_REQUEST_SENT = 0;
56     public final static int TEST_STATUS = 1;
57     public final static int TEST_HEADERS = 2;
58     public final static int TEST_LOCATION_CHANGED = 3;
59     public final static int TEST_DATA = 4;
60     public final static int TEST_ENDDATA = 5;
61     public final static int TEST_ERROR = 6;
62     public final static int TEST_SSL_CERTIFICATE_ERROR = 7;
63 
64     public final static int TEST_NUM_EXPECTS = 8;
65 
66     /* Expected status codes */
67     private int expectMajor = -1;
68     private int expectMinor = -1;
69     private int expectCode = -1;
70 
71     /* Array indicating which event types are expected */
72     private boolean[] expects = new boolean[TEST_NUM_EXPECTS];
73 
74     /* Array indicating which event types are not expected */
75     private boolean[] notExpecting = new boolean[TEST_NUM_EXPECTS];
76 
77     /* Indicates which events have been received */
78     private boolean[] eventsReceived = new boolean[TEST_NUM_EXPECTS];
79 
80     /* Redirection variables */
81     private String expectLocation;
82     private int expectPermanent = -1;
83 
84     /* Content data expected to be received */
85     private byte[] expectData;
86     private int expectDataLength = -1;
87 
88     private int expectErrorId = -1;
89 
90     private int expectSslErrors = -1;
91     private SslCertificate expectCertificate;
92 
93     public class TestHeader {
TestHeader(String n, String v)94         public TestHeader(String n, String v) {
95             name = n;
96             value = v;
97         }
98         public String name;
99         public String value;
100     }
101 
102     private ArrayList<TestHeader> expectHeaders = new ArrayList<TestHeader>();
103 
104     /* Holds failure details */
105     private StringBuffer expectDetails = new StringBuffer();
106 
107     /* If we use a request handle, we retain a reference here for redirects
108      * using setupRedirect
109      */
110     private RequestHandle mRequestHandle;
111 
112     /* The low level API uses this reference also for non-delayed requests */
113     private LowLevelNetRunner netRunner;
114 
TestEventHandler()115     public TestEventHandler() {
116         for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
117             expects[i] = false;
118             notExpecting[i] = false;
119             eventsReceived[i] = false;
120         }
121     }
122 
123     /**
124      * Implementation of EventHandler method called when a request has been
125      * sent. If the test is waiting for this call, it will be signalled,
126      * otherwise this method will trigger the response to be read
127      * automatically.
128      */
requestSent()129     public void requestSent() {
130       Log.v(LOGTAG, "TestEventHandler:requestSent()");
131       expects[TEST_REQUEST_SENT] = false;
132       eventsReceived[TEST_REQUEST_SENT] = true;
133       if (notExpecting[TEST_REQUEST_SENT]) {
134           expectDetails.append("Request sent event received but not expected");
135           expectDetails.append("\r\n");
136       }
137 
138       if (useLowLevel) {
139         if (delayResponse) {
140           synchronized (syncObj) {
141             syncObj.notifyAll();
142           }
143         } else {
144             // mRequest.startReadingResponse();
145         }
146       }
147     }
148 
149     /**
150      * Implements the EventHandler status method called when a server status
151      * response is received.
152      * @param major_version The HTTP major version
153      * @param minor_version The HTTP minor version
154      * @param code The status code
155      * @param reason_phrase A reason phrase passed to us by the server
156      */
status(int major_version, int minor_version, int code, String reason_phrase)157     public void status(int major_version, int minor_version,
158         int code, String reason_phrase) {
159       if (false) {
160         Log.v(LOGTAG, "TestEventHandler:status() major: " + major_version +
161             " minor: " + minor_version +
162             " code: " + code +
163             " reason: " + reason_phrase);
164       }
165 
166       eventsReceived[TEST_STATUS] = true;
167       if (notExpecting[TEST_STATUS]) {
168         expectDetails.append("Status event received but not expected");
169         expectDetails.append("\r\n");
170       }
171 
172       majorVersion = major_version;
173       minorVersion = minor_version;
174       responseCode = code;
175       reasonPhrase = reason_phrase;
176 
177       if (expectMajor != -1) {
178         if (expectMajor == major_version) {
179           expectMajor = -1;
180         } else {
181           expectDetails.append("Major version expected:"+expectMajor+
182               " got:"+major_version);
183           expectDetails.append("\r\n");
184         }
185       }
186 
187       if (expectMinor != -1) {
188         if (expectMinor == minor_version) {
189           expectMinor = -1;
190         } else {
191           expectDetails.append("Minor version expected:"+expectMinor+
192               " got:"+minor_version);
193           expectDetails.append("\r\n");
194         }
195       }
196 
197       if (expectCode != -1) {
198         if (expectCode == code) {
199           expectCode = -1;
200         } else {
201           expectDetails.append("Status code expected:"+expectCode+
202               " got:"+code);
203           expectDetails.append("\r\n");
204         }
205       }
206 
207 
208       if ((expectMajor == -1) && (expectMinor == -1) && (expectCode == -1)) {
209         expects[TEST_STATUS] = false;
210       } else {
211         System.out.println("MAJOR = "+expectMajor+" MINOR = "+expectMinor+
212             " CODE = "+expectCode);
213       }
214     }
215 
216     /**
217      * Implements the EventHandler headers method called when a server
218      * sends header fields
219      */
headers(Headers headers)220     public void headers(Headers headers) {
221         if (false) {
222             Log.v(LOGTAG, "TestEventHandler:headers()");
223         }
224         expects[TEST_HEADERS] = false;
225 
226         if (notExpecting[TEST_HEADERS]) {
227             expectDetails.append("Header event received but not expected");
228             expectDetails.append("\r\n");
229         }
230 
231         /* Check through headers received for matches with expected
232          * headers */
233         if (expectHeaders.isEmpty()) {
234             return;
235         }
236 
237         for (int i = expectHeaders.size() - 1; i >= 0; i--) {
238             TestHeader h =  expectHeaders.get(i);
239             System.out.println("Expected header name: " + h.name);
240             String s = null;
241             switch (h.name.hashCode()) {
242             case -1132779846:
243                 s = Long.toString(headers.getContentLength());
244                 break;
245             case 785670158:
246                 s = headers.getContentType();
247                 break;
248             case 2095084583:
249                 s = headers.getContentEncoding();
250                 break;
251             case 1901043637:
252                 s = headers.getLocation();
253                 break;
254             case -243037365:
255                 s = headers.getWwwAuthenticate();
256                 break;
257             case -301767724:
258                 s = headers.getProxyAuthenticate();
259                 break;
260             case -1267267485:
261                 s = headers.getContentDisposition();
262                 break;
263             case 1397189435:
264                 s = headers.getAcceptRanges();
265                 break;
266             case -1309235404:
267                 s = headers.getExpires();
268                 break;
269             case -208775662:
270                 s = headers.getCacheControl();
271                 break;
272             case 150043680:
273                 s = headers.getLastModified();
274                 break;
275             case 3123477:
276                 s = headers.getEtag();
277                 break;
278             case -775651618:
279                 int ct = headers.getConnectionType();
280                 if (ct == Headers.CONN_CLOSE) {
281                     s = HTTP.CONN_CLOSE;
282                 } else if (ct == Headers.CONN_KEEP_ALIVE) {
283                     s = HTTP.CONN_KEEP_ALIVE;
284                 }
285                 break;
286             default:
287                 s = null;
288 
289             }
290             if (evaluateHeader(h, s)) {
291                 expectHeaders.remove(i);
292             }
293         }
294 
295     }
296 
evaluateHeader(TestHeader h, String value)297     public boolean evaluateHeader(TestHeader h, String value) {
298         if (value == null) {
299             expects[TEST_HEADERS] = true;
300             System.out.print(" Missing!  ");
301             expectDetails.append(" missing header " + h.name);
302             return false;
303         }
304         if (h.value == null) {
305             System.out.println("Expect value = null");
306             return true;
307         }
308         System.out.println("Expect value = " +
309                 (h.value.toLowerCase()) + " got " +
310                 value.toLowerCase());
311 
312         if (!h.value.equalsIgnoreCase(value)) {
313             expectDetails.append("expect header value " + h.value +
314                     " got " + value);
315             expects[TEST_HEADERS] = true;
316             return false;
317         }
318         return true;
319     }
320     /**
321      * Implements the EventHandler locationChanged method called when a server
322      * sends a redirect message
323      * @param newLocation The URL to the new server
324      * @param permanent Indicator of whether this is a permanent change
325      */
locationChanged(String newLocation, boolean permanent)326     public void locationChanged(String newLocation, boolean permanent) {
327       if (false) {
328         Log.v(LOGTAG, "TestEventHandler: locationChanged() " +
329             newLocation + " permanent " + permanent);
330       }
331 
332       eventsReceived[TEST_LOCATION_CHANGED] = true;
333       if (notExpecting[TEST_LOCATION_CHANGED]) {
334         expectDetails.append("Location changed event received but "+
335             "not expected");
336         expectDetails.append("\r\n");
337       }
338 
339       if (expectLocation != null) {
340         if (expectLocation.equals(newLocation)) {
341           expectLocation = null;
342         } else {
343           expectDetails.append("Location expected:"+expectLocation+
344               " got:"+newLocation);
345           expectDetails.append("\r\n");
346         }
347       }
348 
349       if (expectPermanent != -1) {
350         if (((expectPermanent == 0) && !permanent) ||
351             ((expectPermanent == 1) && permanent)){
352           expectPermanent = -1;
353         } else {
354           expectDetails.append("Location permanent expected:"+
355               expectPermanent+" got"+permanent);
356           expectDetails.append("\r\n");
357         }
358       }
359 
360       if ((expectLocation == null) && (expectPermanent == -1))
361         expects[TEST_LOCATION_CHANGED] = false;
362     }
363 
364     /**
365      * Implements the EventHandler data method called when a server
366      * sends content data
367      * @param data The byte array content
368      * @param len The length of the data
369      */
data(byte[] data, int len)370     public void data(byte[] data, int len) {
371       boolean mismatch = false;
372 
373       if (false) {
374         Log.v(LOGTAG, "TestEventHandler: data() " + len + " bytes");
375       }
376 
377       eventsReceived[TEST_DATA] = true;
378       if (notExpecting[TEST_DATA]) {
379         expectDetails.append("Data event received but not expected");
380         expectDetails.append("\r\n");
381       }
382 
383       Log.v(LOGTAG, new String(data, 0, len));
384 
385       if (expectDataLength != -1) {
386         if (expectDataLength == len) {
387           expectDataLength = -1;
388         } else {
389           expectDetails.append("expect data length mismatch expected:"+
390               expectDataLength+" got:"+len);
391           expectDetails.append("\r\n");
392         }
393 
394         /* Check data only if length is the same */
395         if ((expectDataLength == -1) && expectData != null) {
396           for (int i = 0; i < len; i++) {
397             if (expectData[i] != data[i]) {
398               mismatch = true;
399               expectDetails.append("Expect data mismatch at byte "+
400                   i+" expected:"+expectData[i]+" got:"+data[i]);
401               expectDetails.append("\r\n");
402               break;
403             }
404           }
405         }
406       }
407 
408       if ((expectDataLength == -1) || !mismatch)
409         expects[TEST_DATA] = false;
410     }
411 
412     /**
413      * Implements the EventHandler endData method called to
414      * indicate completion or a request
415      */
endData()416     public void endData() {
417       if (false) {
418         Log.v(LOGTAG, "TestEventHandler: endData() called");
419       }
420 
421       eventsReceived[TEST_ENDDATA] = true;
422       if (notExpecting[TEST_ENDDATA]) {
423         expectDetails.append("End data event received but not expected");
424         expectDetails.append("\r\n");
425       }
426 
427       expects[TEST_ENDDATA] = false;
428 
429       if (useLowLevel) {
430         if (delayResponse) {
431           synchronized (syncObj) {
432             syncObj.notifyAll();
433           }
434         } else {
435           if (netRunner != null) {
436             System.out.println("TestEventHandler: endData() stopping "+
437                 netRunner);
438             netRunner.decrementRunCount();
439           }
440         }
441       }
442     }
443 
444     /**
445      * Implements the EventHandler certificate method called every
446      * time a resource is loaded via a secure connection
447      */
certificate(SslCertificate certificate)448     public void certificate(SslCertificate certificate) {}
449 
450     /**
451      * Implements the EventHandler error method called when a server
452      * sends header fields
453      * @param id Status code of the error
454      * @param description Brief description of the error
455      */
error(int id, String description)456     public void error(int id, String description) {
457       if (false) {
458         Log.v(LOGTAG, "TestEventHandler: error() called Id:" + id +
459             " description " + description);
460       }
461 
462       eventsReceived[TEST_ERROR] = true;
463       if (notExpecting[TEST_ERROR]) {
464         expectDetails.append("Error event received but not expected");
465         expectDetails.append("\r\n");
466       }
467       if (expectErrorId != -1) {
468         if (expectErrorId == id) {
469           expectErrorId = -1;
470         } else {
471           expectDetails.append("Error Id expected:"+expectErrorId+
472               " got:"+id);
473           expectDetails.append("\r\n");
474         }
475       }
476 
477       if (expectErrorId == -1)
478         expects[TEST_ERROR] = false;
479 
480       if (useLowLevel) {
481         if (delayResponse) {
482           synchronized (syncObj) {
483             syncObj.notifyAll();
484           }
485         } else {
486           if (netRunner != null) {
487             System.out.println("TestEventHandler: endData() stopping "+
488                 netRunner);
489             netRunner.decrementRunCount();
490           }
491         }
492       }
493     }
494 
495     /**
496      * SSL certificate error callback. Handles SSL error(s) on the way
497      * up to the user.
498      */
handleSslErrorRequest(SslError error)499     public boolean handleSslErrorRequest(SslError error) {
500       int primaryError = error.getPrimaryError();
501 
502       if (false) {
503         Log.v(LOGTAG, "TestEventHandler: handleSslErrorRequest(): "+
504               " primary error:" + primaryError +
505               " certificate: " + error.getCertificate());
506       }
507 
508       eventsReceived[TEST_SSL_CERTIFICATE_ERROR] = true;
509       if (notExpecting[TEST_SSL_CERTIFICATE_ERROR]) {
510         expectDetails.append("SSL Certificate error event received "+
511             "but not expected");
512         expectDetails.append("\r\n");
513       }
514 
515       if (expectSslErrors != -1) {
516         if (expectSslErrors == primaryError) {
517             expectSslErrors = -1;
518         } else {
519             expectDetails.append("SslCertificateError id expected:"+
520                 expectSslErrors+" got: " + primaryError);
521             expectDetails.append("\r\n");
522         }
523       }
524 
525       // SslCertificate match here?
526 
527       if (expectSslErrors == -1) // && expectSslCertificate == certificate?
528         expects[TEST_SSL_CERTIFICATE_ERROR] = false;
529 
530       // return false so that we won't block the thread
531       return false;
532     }
533 
534     /**
535      * Use the low level net runner with no delayed response
536      * @param runner The LowLevelNetRunner object
537      */
setNetRunner(LowLevelNetRunner runner)538     public void setNetRunner(LowLevelNetRunner runner) {
539       setNetRunner(runner, false);
540     }
541 
542     /**
543      * Use the low level net runner and specify if the response
544      * should be delayed
545      * @param runner The LowLevelNetRunner object
546      * @param delayedResponse Set to true is you will use the
547      * waitForRequestSent/waitForRequestResponse routines
548      */
setNetRunner(LowLevelNetRunner runner, boolean delayedResponse)549     public void setNetRunner(LowLevelNetRunner runner,
550         boolean delayedResponse) {
551       netRunner = runner;
552       useLowLevel = true;
553       delayResponse = delayedResponse;
554 
555       if (!delayResponse)
556         netRunner.incrementRunCount();
557     }
558 
559     /**
560      * Enable this listeners Request object to read server responses.
561      * This should only be used in conjunction with setDelayResponse(true)
562      */
waitForRequestResponse()563     public void waitForRequestResponse() {
564       if (!delayResponse || !useLowLevel) {
565         Log.d(LOGTAG, " Cant do this without delayReponse set ");
566         return;
567       }
568 
569       //if (mRequest != null) {
570           // mRequest.startReadingResponse();
571       // }
572       /* Now wait for the response to be completed either through endData
573        * or an error
574        */
575       synchronized (syncObj) {
576         try {
577           syncObj.wait();
578         } catch (InterruptedException e) {
579         }
580       }
581     }
582 
583     /**
584      * Enable this listeners Request object to read server responses.
585      * This should only be used in conjunction with setDelayResponse(true)
586      */
waitForRequestSent()587     public void waitForRequestSent() {
588       if (!delayResponse || !useLowLevel) {
589         Log.d(LOGTAG, " Cant do this without delayReponse set ");
590         return;
591       }
592 
593       /* Now wait for the response to be completed either through endData
594        * or an error
595        */
596       synchronized (syncObj) {
597         try {
598           syncObj.wait();
599         } catch (InterruptedException e) {
600         }
601       }
602     }
603 
604     /* Test expected values - these routines set the tests expectations */
605 
expectRequestSent()606     public void expectRequestSent() {
607         expects[TEST_REQUEST_SENT] = true;
608     }
609 
expectNoRequestSent()610     public void expectNoRequestSent() {
611         notExpecting[TEST_REQUEST_SENT] = true;
612     }
613 
expectStatus()614     public void expectStatus() {
615         expects[TEST_STATUS] = true;
616     }
617 
expectNoStatus()618     public void expectNoStatus() {
619         notExpecting[TEST_STATUS] = true;
620     }
621 
expectStatus(int major, int minor, int code)622     public void expectStatus(int major, int minor, int code) {
623         expects[TEST_STATUS] = true;
624         expectMajor = major;
625         expectMinor = minor;
626         expectCode = code;
627     }
628 
expectStatus(int code)629     public void expectStatus(int code) {
630         expects[TEST_STATUS] = true;
631         expectCode = code;
632     }
633 
expectHeaders()634     public void expectHeaders() {
635         expects[TEST_HEADERS] = true;
636     }
637 
expectNoHeaders()638     public void expectNoHeaders() {
639         notExpecting[TEST_HEADERS] = true;
640     }
641 
expectHeaderAdd(String name)642     public void expectHeaderAdd(String name) {
643         expects[TEST_HEADERS] = true;
644         TestHeader h = new TestHeader(name.toLowerCase(), null);
645         expectHeaders.add(h);
646     }
647 
expectHeaderAdd(String name, String value)648     public void expectHeaderAdd(String name, String value) {
649         expects[TEST_HEADERS] = true;
650         TestHeader h = new TestHeader(name.toLowerCase(), value);
651         expectHeaders.add(h);
652     }
653 
expectLocationChanged()654     public void expectLocationChanged() {
655         expects[TEST_LOCATION_CHANGED] = true;
656     }
657 
expectNoLocationChanged()658     public void expectNoLocationChanged() {
659             notExpecting[TEST_LOCATION_CHANGED] = true;
660     }
661 
expectLocationChanged(String newLocation)662     public void expectLocationChanged(String newLocation) {
663         expects[TEST_LOCATION_CHANGED] = true;
664         expectLocation = newLocation;
665     }
666 
expectLocationChanged(String newLocation, boolean permanent)667     public void expectLocationChanged(String newLocation, boolean permanent) {
668         expects[TEST_LOCATION_CHANGED] = true;
669         expectLocation = newLocation;
670         expectPermanent = permanent ? 1 : 0;
671     }
672 
expectData()673     public void expectData() {
674         expects[TEST_DATA] = true;
675     }
676 
expectNoData()677     public void expectNoData() {
678         notExpecting[TEST_DATA] = true;
679     }
680 
expectData(int len)681     public void expectData(int len) {
682         expects[TEST_DATA] = true;
683         expectDataLength = len;
684     }
685 
expectData(byte[] data, int len)686     public void expectData(byte[] data, int len) {
687         expects[TEST_DATA] = true;
688         expectData = new byte[len];
689         expectDataLength = len;
690 
691         for (int i = 0; i < len; i++) {
692             expectData[i] = data[i];
693         }
694     }
695 
expectEndData()696     public void expectEndData() {
697         expects[TEST_ENDDATA] = true;
698     }
699 
expectNoEndData()700     public void expectNoEndData() {
701             notExpecting[TEST_ENDDATA] = true;
702     }
703 
expectError()704     public void expectError() {
705         expects[TEST_ERROR] = true;
706     }
707 
expectNoError()708     public void expectNoError() {
709         notExpecting[TEST_ERROR] = true;
710     }
711 
expectError(int errorId)712     public void expectError(int errorId) {
713         expects[TEST_ERROR] = true;
714         expectErrorId = errorId;
715     }
716 
expectSSLCertificateError()717     public void expectSSLCertificateError() {
718         expects[TEST_SSL_CERTIFICATE_ERROR] = true;
719     }
720 
expectNoSSLCertificateError()721     public void expectNoSSLCertificateError() {
722             notExpecting[TEST_SSL_CERTIFICATE_ERROR] = true;
723     }
724 
expectSSLCertificateError(int errors)725     public void expectSSLCertificateError(int errors) {
726         expects[TEST_SSL_CERTIFICATE_ERROR] = true;
727         expectSslErrors = errors;
728     }
729 
expectSSLCertificateError(SslCertificate certificate)730     public void expectSSLCertificateError(SslCertificate certificate) {
731         expects[TEST_SSL_CERTIFICATE_ERROR] = true;
732         expectCertificate = certificate;
733     }
734 
735     /**
736      * Test to see if current expectations match recieved information
737      * @return True is all expected results have been matched
738      */
expectPassed()739     public boolean expectPassed() {
740         for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
741             if (expects[i] == true) {
742                 return false;
743             }
744         }
745 
746         for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
747             if (eventsReceived[i] && notExpecting[i]) {
748                 return false;
749             }
750         }
751         return true;
752     }
753 
754     /**
755      * Return message indicating expectation failures
756      */
getFailureMessage()757     public String getFailureMessage() {
758         return expectDetails.toString();
759     }
760 
761     /**
762      * Reset all expectation values for re-use
763      */
resetExpects()764     public void resetExpects() {
765         expectMajor = -1;
766         expectMinor = -1;
767         expectCode = -1;
768         expectLocation = null;
769         expectPermanent = -1;
770         expectErrorId = -1;
771         expectSslErrors = -1;
772         expectCertificate = null;
773         expectDetails.setLength(0);
774         expectHeaders.clear();
775 
776         for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
777             expects[i] = false;
778             notExpecting[i] = false;
779             eventsReceived[i] = false;
780         }
781 
782         for (int i = 0; i < expectDataLength; i++) {
783             expectData[i] = 0;
784         }
785 
786         expectDataLength = -1;
787     }
788 
789     /**
790      * Attach the RequestHandle to this handler
791      * @param requestHandle The RequestHandle
792      */
attachRequestHandle(RequestHandle requestHandle)793     public void attachRequestHandle(RequestHandle requestHandle) {
794         if (false) {
795             Log.v(LOGTAG, "TestEventHandler.attachRequestHandle(): " +
796                     "requestHandle: " +  requestHandle);
797         }
798         mRequestHandle = requestHandle;
799     }
800 
801     /**
802      * Detach the RequestHandle
803      */
detachRequestHandle()804     public void detachRequestHandle() {
805         if (false) {
806             Log.v(LOGTAG, "TestEventHandler.detachRequestHandle(): " +
807                     "requestHandle: " + mRequestHandle);
808         }
809         mRequestHandle = null;
810     }
811 
812     protected final static String LOGTAG = "http";
813 }
814