1 /*
2  * Copyright (C) 2017 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 com.android.phone.testapps.embmsmw;
18 
19 import android.telephony.mbms.StreamingService;
20 import android.telephony.mbms.StreamingServiceCallback;
21 
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Random;
25 
26 // Tracks the states of the streams for a single (uid, appName, subscriptionId) tuple
27 public class AppActiveStreams {
28     // Wrapper for a pair (StreamingServiceCallback, streaming state)
29     private static class StreamCallbackWithState {
30         private final StreamingServiceCallback mCallback;
31         private int mState;
32         private int mMethod;
33         private boolean mMethodSet = false;
34 
StreamCallbackWithState(StreamingServiceCallback callback, int state, int method)35         StreamCallbackWithState(StreamingServiceCallback callback, int state, int method) {
36             mCallback = callback;
37             mState = state;
38             mMethod = method;
39         }
40 
getCallback()41         public StreamingServiceCallback getCallback() {
42             return mCallback;
43         }
44 
getState()45         public int getState() {
46             return mState;
47         }
48 
setState(int state)49         public void setState(int state) {
50             mState = state;
51         }
52 
getMethod()53         public int getMethod() {
54             return mMethod;
55         }
56 
setMethod(int method)57         public void setMethod(int method) {
58             mMethod = method;
59             mMethodSet = true;
60         }
61 
isMethodSet()62         public boolean isMethodSet() {
63             return mMethodSet;
64         }
65     }
66 
67     // Stores the state and callback per service ID.
68     private final Map<String, StreamCallbackWithState> mStreamStates = new HashMap<>();
69     private final FrontendAppIdentifier mAppIdentifier;
70     private final Random mRand = new Random();
71 
AppActiveStreams(FrontendAppIdentifier appIdentifier)72     public AppActiveStreams(FrontendAppIdentifier appIdentifier) {
73         mAppIdentifier = appIdentifier;
74     }
75 
getStateForService(String serviceId)76     public int getStateForService(String serviceId) {
77         StreamCallbackWithState callbackWithState = mStreamStates.get(serviceId);
78         return callbackWithState == null ?
79                 StreamingService.STATE_STOPPED : callbackWithState.getState();
80     }
81 
startStreaming(String serviceId, StreamingServiceCallback callback, int reason)82     public void startStreaming(String serviceId, StreamingServiceCallback callback, int reason) {
83         if (mStreamStates.get(serviceId) != null) {
84             // error - already started
85             return;
86         }
87         for (StreamCallbackWithState c : mStreamStates.values()) {
88             if (c.getCallback() == callback) {
89                 // error - callback already in use
90                 return;
91             }
92         }
93         mStreamStates.put(serviceId,
94                 new StreamCallbackWithState(callback, StreamingService.STATE_STARTED,
95                         StreamingService.UNICAST_METHOD));
96         callback.onStreamStateUpdated(StreamingService.STATE_STARTED, reason);
97         updateStreamingMethod(serviceId);
98     }
99 
stopStreaming(String serviceId, int reason)100     public void stopStreaming(String serviceId, int reason) {
101         StreamCallbackWithState entry = mStreamStates.get(serviceId);
102 
103         if (entry != null) {
104             if (entry.getState() != StreamingService.STATE_STOPPED) {
105                 entry.setState(StreamingService.STATE_STOPPED);
106                 entry.getCallback().onStreamStateUpdated(StreamingService.STATE_STOPPED, reason);
107             }
108         }
109     }
110 
dispose(String serviceId)111     public void dispose(String serviceId) {
112         mStreamStates.remove(serviceId);
113     }
114 
updateStreamingMethod(String serviceId)115     private void updateStreamingMethod(String serviceId) {
116         StreamCallbackWithState callbackWithState = mStreamStates.get(serviceId);
117         if (callbackWithState != null) {
118             int oldMethod = callbackWithState.getMethod();
119             int newMethod = oldMethod;
120             if (mRand.nextInt(99) < 50) {
121                 newMethod = StreamingService.UNICAST_METHOD;
122             } else {
123                 newMethod = StreamingService.BROADCAST_METHOD;
124             }
125             if (newMethod != oldMethod || callbackWithState.isMethodSet()) {
126                 callbackWithState.setMethod(newMethod);
127                 callbackWithState.getCallback().onStreamMethodUpdated(newMethod);
128             }
129         }
130     }
131 }
132