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 17package com.android.phone.testapps.embmsfrontend; 18 19import android.app.Activity; 20import android.content.Context; 21import android.net.Uri; 22import android.os.Bundle; 23import android.os.Handler; 24import android.os.HandlerThread; 25import android.telephony.MbmsStreamingSession; 26import android.telephony.mbms.MbmsStreamingSessionCallback; 27import android.telephony.mbms.StreamingService; 28import android.telephony.mbms.StreamingServiceInfo; 29import android.view.View; 30import android.view.ViewGroup; 31import android.widget.AdapterView; 32import android.widget.ArrayAdapter; 33import android.widget.Button; 34import android.widget.Spinner; 35import android.widget.TextView; 36import android.widget.Toast; 37 38import java.util.Collections; 39import java.util.HashMap; 40import java.util.List; 41import java.util.Locale; 42import java.util.Map; 43import java.util.NoSuchElementException; 44 45public class EmbmsTestStreamingApp extends Activity { 46 private MbmsStreamingSessionCallback mStreamingListener = new MbmsStreamingSessionCallback() { 47 @Override 48 public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) { 49 EmbmsTestStreamingApp.this.runOnUiThread(() -> 50 Toast.makeText(EmbmsTestStreamingApp.this, 51 "Got services length " + services.size(), 52 Toast.LENGTH_SHORT).show()); 53 updateStreamingServicesList(services); 54 } 55 56 @Override 57 public void onMiddlewareReady() { 58 runOnUiThread(() -> Toast.makeText(EmbmsTestStreamingApp.this, "Successfully bound", 59 Toast.LENGTH_SHORT).show()); 60 } 61 }; 62 63 private final class StreamingServiceInfoAdapter 64 extends ArrayAdapter<StreamingServiceInfo> { 65 public StreamingServiceInfoAdapter(Context context, int resource) { 66 super(context, resource); 67 } 68 69 private String getName(StreamingServiceInfo info) { 70 Locale locale = Locale.getDefault(); 71 try { 72 return info.getNameForLocale(locale).toString(); 73 } catch (NoSuchElementException e) { 74 locale = info.getLocales().iterator().next(); 75 return info.getNameForLocale(locale).toString(); 76 } 77 } 78 79 @Override 80 public View getView(int position, View convertView, ViewGroup parent) { 81 StreamingServiceInfo info = getItem(position); 82 TextView result = new TextView(EmbmsTestStreamingApp.this); 83 result.setText(getName(info)); 84 return result; 85 } 86 87 @Override 88 public View getDropDownView(int position, View convertView, ViewGroup parent) { 89 StreamingServiceInfo info = getItem(position); 90 TextView result = new TextView(EmbmsTestStreamingApp.this); 91 String text = "name=" 92 + getName(info) 93 + ", " 94 + "serviceId=" 95 + info.getServiceId(); 96 result.setText(text); 97 return result; 98 } 99 100 public void update(List<StreamingServiceInfo> services) { 101 clear(); 102 addAll(services); 103 } 104 } 105 106 private final class TrackedStreamAdapter extends ArrayAdapter<String> { 107 public TrackedStreamAdapter(Context context) { 108 super(context, android.R.layout.simple_spinner_item); 109 setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 110 } 111 112 @Override 113 public View getView(int position, View convertView, ViewGroup parent) { 114 String serviceId = getItem(position); 115 StreamingServiceTracker tracker = mStreamingServiceTrackerById.get(serviceId); 116 TextView result = new TextView(EmbmsTestStreamingApp.this); 117 result.setText(tracker == null ? "" : tracker.toString()); 118 return result; 119 } 120 121 @Override 122 public View getDropDownView(int position, View convertView, ViewGroup parent) { 123 String serviceId = getItem(position); 124 StreamingServiceTracker tracker = mStreamingServiceTrackerById.get(serviceId); 125 TextView result = new TextView(EmbmsTestStreamingApp.this); 126 result.setText(tracker.toString()); 127 return result; 128 } 129 } 130 131 private MbmsStreamingSession mStreamingManager = null; 132 133 private Handler mHandler; 134 private HandlerThread mHandlerThread; 135 136 private TrackedStreamAdapter mTrackedStreamingServiceAdapter; 137 private Spinner mStreamSelector; 138 private StreamingServiceInfoAdapter mStreamingServicesDisplayAdapter; 139 private final Map<String, StreamingServiceTracker> mStreamingServiceTrackerById = 140 new HashMap<>(); 141 142 @Override 143 protected void onCreate(Bundle savedInstanceState) { 144 super.onCreate(savedInstanceState); 145 setContentView(R.layout.activity_main); 146 147 mHandlerThread = new HandlerThread("EmbmsSampleFrontendWorker"); 148 mHandlerThread.start(); 149 mHandler = new Handler(mHandlerThread.getLooper()); 150 mStreamingServicesDisplayAdapter = 151 new StreamingServiceInfoAdapter(this, android.R.layout.simple_spinner_item); 152 mTrackedStreamingServiceAdapter = new TrackedStreamAdapter(this); 153 154 Button bindButton = (Button) findViewById(R.id.bind_button); 155 bindButton.setOnClickListener((view) -> { 156 mStreamingManager = MbmsStreamingSession.create( 157 EmbmsTestStreamingApp.this, mStreamingListener, mHandler); 158 }); 159 160 Button getStreamingServicesButton = (Button) 161 findViewById(R.id.get_streaming_services_button); 162 getStreamingServicesButton.setOnClickListener((view) -> { 163 if (mStreamingManager == null) { 164 Toast.makeText(EmbmsTestStreamingApp.this, 165 "No streaming service bound", Toast.LENGTH_SHORT).show(); 166 return; 167 } 168 mStreamingManager.requestUpdateStreamingServices(Collections.singletonList("Class1")); 169 }); 170 171 final Spinner serviceSelector = (Spinner) findViewById(R.id.available_streaming_services); 172 mStreamingServicesDisplayAdapter.setDropDownViewResource( 173 android.R.layout.simple_spinner_dropdown_item); 174 serviceSelector.setAdapter(mStreamingServicesDisplayAdapter); 175 176 mStreamSelector = (Spinner) findViewById(R.id.curr_streams); 177 mTrackedStreamingServiceAdapter.setDropDownViewResource( 178 android.R.layout.simple_spinner_dropdown_item); 179 mStreamSelector.setAdapter(mTrackedStreamingServiceAdapter); 180 mStreamSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 181 @Override 182 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 183 String serviceId = (String) mStreamSelector.getItemAtPosition(position); 184 StreamingServiceTracker tracker = mStreamingServiceTrackerById.get(serviceId); 185 186 setStreamStateDisplay(String.valueOf(tracker.getState())); 187 setUriDisplay(tracker.getUri()); 188 } 189 190 @Override 191 public void onNothingSelected(AdapterView<?> parent) { 192 clearStateAndUriDisplay(); 193 } 194 }); 195 196 Button startStreamingButton = (Button) findViewById(R.id.start_streaming_button); 197 startStreamingButton.setOnClickListener((view) -> { 198 if (mStreamingManager == null) { 199 Toast.makeText(EmbmsTestStreamingApp.this, 200 "No streaming service bound", Toast.LENGTH_SHORT).show(); 201 return; 202 } 203 StreamingServiceInfo serviceInfo = 204 (StreamingServiceInfo) serviceSelector.getSelectedItem(); 205 if (serviceInfo == null) { 206 Toast.makeText(EmbmsTestStreamingApp.this, 207 "No streaming service selected", Toast.LENGTH_SHORT).show(); 208 return; 209 } 210 211 StreamingServiceTracker tracker = new StreamingServiceTracker(this, serviceInfo); 212 if (tracker.startStreaming(mStreamingManager)) { 213 mStreamingServiceTrackerById.put(serviceInfo.getServiceId(), tracker); 214 mTrackedStreamingServiceAdapter.add(serviceInfo.getServiceId()); 215 } 216 }); 217 218 Button stopStreamingButton = (Button) findViewById(R.id.stop_streaming_button); 219 stopStreamingButton.setOnClickListener((view) -> { 220 if (getSelectedTrackedStream() == null) { 221 Toast.makeText(EmbmsTestStreamingApp.this, 222 "No streams selected", Toast.LENGTH_SHORT).show(); 223 return; 224 } 225 StreamingServiceTracker stream = getSelectedTrackedStream(); 226 stream.stopStreaming(); 227 }); 228 229 Button disposeManagerButton = (Button) findViewById(R.id.dispose_manager_button); 230 disposeManagerButton.setOnClickListener((view) -> { 231 clearStateAndUriDisplay(); 232 mTrackedStreamingServiceAdapter.clear(); 233 mStreamingServicesDisplayAdapter.update(Collections.emptyList()); 234 mStreamingServiceTrackerById.clear(); 235 mStreamingManager.close(); 236 }); 237 } 238 239 @Override 240 protected void onDestroy() { 241 super.onDestroy(); 242 mHandlerThread.quit(); 243 } 244 245 private void updateStreamingServicesList(List<StreamingServiceInfo> services) { 246 runOnUiThread(() -> mStreamingServicesDisplayAdapter.update(services)); 247 } 248 249 private StreamingServiceTracker getSelectedTrackedStream() { 250 String serviceId = (String) mStreamSelector.getSelectedItem(); 251 return mStreamingServiceTrackerById.get(serviceId); 252 } 253 254 private void setUriDisplay(Uri uri) { 255 runOnUiThread(() -> { 256 TextView uriField = (TextView) findViewById(R.id.curr_streaming_uri); 257 uriField.setText(uri.toSafeString()); 258 }); 259 } 260 261 private void setStreamStateDisplay(String stateString) { 262 runOnUiThread(() -> { 263 TextView uriField = (TextView) findViewById(R.id.stream_state); 264 uriField.setText(stateString); 265 }); 266 } 267 268 private void setStreamMethodDisplay(int method) { 269 runOnUiThread(() -> { 270 String methodString = "UNKNOWN METHOD"; 271 switch (method) { 272 case StreamingService.BROADCAST_METHOD: { 273 methodString = "BROADCAST"; 274 break; 275 } 276 case StreamingService.UNICAST_METHOD: { 277 methodString = "UNICAST"; 278 break; 279 } 280 } 281 TextView methodField = (TextView) findViewById(R.id.curr_streaming_method); 282 methodField.setText(methodString); 283 }); 284 } 285 286 private void clearStateAndUriDisplay() { 287 setUriDisplay(Uri.EMPTY); 288 setStreamStateDisplay(""); 289 setStreamMethodDisplay(StreamingService.UNICAST_METHOD); 290 } 291 292 public void updateUri() { 293 Uri uri = getSelectedTrackedStream() == null ? 294 Uri.EMPTY : getSelectedTrackedStream().getUri(); 295 setUriDisplay(uri); 296 } 297 298 public void updateStreamingState() { 299 String stateString = getSelectedTrackedStream() == null ? 300 "" : String.valueOf(getSelectedTrackedStream().getState()); 301 setStreamStateDisplay(stateString); 302 } 303 304 /** implementation of updateMethod callback */ 305 public void updateMethod() { 306 StreamingServiceTracker serviceTracker = getSelectedTrackedStream(); 307 if (serviceTracker == null) { 308 setStreamMethodDisplay(StreamingService.UNICAST_METHOD); 309 } else { 310 setStreamMethodDisplay(serviceTracker.getMethod()); 311 } 312 } 313} 314