1 /*
2  * Copyright (C) 2017 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package com.google.android.mobly.snippet.event;
18 
19 import androidx.annotation.Nullable;
20 import com.google.android.mobly.snippet.Snippet;
21 import com.google.android.mobly.snippet.rpc.Rpc;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.concurrent.LinkedBlockingDeque;
26 import java.util.concurrent.TimeUnit;
27 import org.json.JSONException;
28 import org.json.JSONObject;
29 
30 public class EventSnippet implements Snippet {
31     private static class EventSnippetException extends Exception {
32         private static final long serialVersionUID = 1L;
33 
EventSnippetException(String msg)34         public EventSnippetException(String msg) {
35             super(msg);
36         }
37     }
38 
39     private static final int DEFAULT_TIMEOUT_MILLISECOND = 60 * 1000;
40     private final EventCache mEventCache = EventCache.getInstance();
41 
42     @Rpc(
43             description =
44                     "Blocks until an event of a specified type has been received. The returned event is removed from the cache. Default timeout is 60s.")
eventWaitAndGet( String callbackId, String eventName, @Nullable Integer timeout)45     public JSONObject eventWaitAndGet(
46             String callbackId, String eventName, @Nullable Integer timeout)
47             throws InterruptedException, JSONException, EventSnippetException {
48         // The server side should never wait forever, so we'll use a default timeout is one is not
49         // provided.
50         if (timeout == null) {
51             timeout = DEFAULT_TIMEOUT_MILLISECOND;
52         }
53         String qId = EventCache.getQueueId(callbackId, eventName);
54         LinkedBlockingDeque<SnippetEvent> q = mEventCache.getEventDeque(qId);
55         SnippetEvent result = q.pollFirst(timeout, TimeUnit.MILLISECONDS);
56         if (result == null) {
57             throw new EventSnippetException("timeout.");
58         }
59         return result.toJson();
60     }
61 
62     @Rpc(
63             description =
64                     "Gets and removes all the events of a certain name that have been received so far. "
65                             + "Non-blocking. Potentially racey since it does not guarantee no event of "
66                             + "the same name will occur after the call.")
eventGetAll(String callbackId, String eventName)67     public List<JSONObject> eventGetAll(String callbackId, String eventName)
68             throws InterruptedException, JSONException {
69         String qId = EventCache.getQueueId(callbackId, eventName);
70         LinkedBlockingDeque<SnippetEvent> q = mEventCache.getEventDeque(qId);
71         ArrayList<JSONObject> results = new ArrayList<>(q.size());
72         ArrayList<SnippetEvent> buffer = new ArrayList<>(q.size());
73         q.drainTo(buffer);
74         for (SnippetEvent snippetEvent : buffer) {
75             results.add(snippetEvent.toJson());
76         }
77         if (results.size() == 0) {
78             return Collections.emptyList();
79         }
80         return results;
81     }
82 
83     @Override
shutdown()84     public void shutdown() {
85         mEventCache.clearAll();
86     }
87 }
88