getStreamingServices for Embms
Add code in frontend app to call getStreamingServices.
Add code in backend to generate a list and return it after some delay.
Test: testapps
Change-Id: I4265149b29daa2fbbfc49196e264c194f896a417
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsTestStreamingService.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsTestStreamingService.java
index c0e601f..11f4e6d 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsTestStreamingService.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsTestStreamingService.java
@@ -16,27 +16,79 @@
package com.android.phone.testapps.embmsmw;
+import android.app.AppOpsManager;
import android.app.Service;
+import android.content.Context;
import android.content.Intent;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.RemoteException;
import android.telephony.mbms.IMbmsStreamingManagerCallback;
import android.telephony.mbms.MbmsException;
+import android.telephony.mbms.StreamingServiceInfo;
import android.telephony.mbms.vendor.IMbmsStreamingService;
import android.telephony.mbms.vendor.MbmsStreamingServiceBase;
import android.util.Log;
+import com.android.internal.os.SomeArgs;
+
+import java.util.Arrays;
+import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.Set;
public class EmbmsTestStreamingService extends Service {
- private final static String TAG = "EmbmsTestStreaming";
- private final Map<String, IMbmsStreamingManagerCallback> mAppCallbacks = new HashMap<>();
+ private static final Set<String> ALLOWED_PACKAGES = new HashSet<String>() {{
+ add("com.android.phone.testapps.embmsfrontend");
+ }};
+
+ private static final String TAG = "EmbmsTestStreaming";
+ private static final int SEND_STREAMING_SERVICES_LIST = 1;
+
+ private final Map<StreamingAppIdentifier, IMbmsStreamingManagerCallback> mAppCallbacks =
+ new HashMap<>();
+
+ private HandlerThread mHandlerThread;
+ private Handler mHandler;
+ private Handler.Callback mWorkerCallback = (msg) -> {
+ switch (msg.what) {
+ case SEND_STREAMING_SERVICES_LIST:
+ SomeArgs args = (SomeArgs) msg.obj;
+ StreamingAppIdentifier appKey = (StreamingAppIdentifier) args.arg1;
+ List<StreamingServiceInfo> services = (List) args.arg2;
+ IMbmsStreamingManagerCallback appCallback = mAppCallbacks.get(appKey);
+ if (appCallback != null) {
+ try {
+ appCallback.streamingServicesUpdated(services);
+ } catch (RemoteException e) {
+ // Assume app has gone away and clean up.
+ }
+ }
+ }
+ return true;
+ };
private final IMbmsStreamingService.Stub mBinder = new MbmsStreamingServiceBase() {
@Override
- public int initialize(IMbmsStreamingManagerCallback listener, String appName, int subId)
- throws MbmsException {
- String appKey = appName + subId;
+ public int initialize(IMbmsStreamingManagerCallback listener, String appName, int subId) {
+ String[] packageNames = getPackageManager().getPackagesForUid(Binder.getCallingUid());
+ if (packageNames == null) {
+ return MbmsException.ERROR_APP_PERMISSIONS_NOT_GRANTED;
+ }
+ boolean isUidAllowed = Arrays.stream(packageNames).anyMatch(ALLOWED_PACKAGES::contains);
+ if (!isUidAllowed) {
+ return MbmsException.ERROR_APP_PERMISSIONS_NOT_GRANTED;
+ }
+
+ StreamingAppIdentifier appKey =
+ new StreamingAppIdentifier(Binder.getCallingUid(), appName, subId);
if (!mAppCallbacks.containsKey(appKey)) {
mAppCallbacks.put(appKey, listener);
} else {
@@ -44,22 +96,57 @@
}
return 0;
}
- };
- @Override
- public void onCreate() {
- super.onCreate();
- logd("EmbmsTestStreamingService onCreate");
- }
+ @Override
+ public int getStreamingServices(String appName, int subscriptionId,
+ List<String> serviceClasses) {
+ StreamingAppIdentifier appKey =
+ new StreamingAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ if (!mAppCallbacks.containsKey(appKey)) {
+ return MbmsException.ERROR_NOT_YET_INITIALIZED;
+ }
+
+ Map<Locale, String> nameDict1 = new HashMap<Locale, String>() {{
+ put(Locale.US, "TestService1");
+ }};
+ Map<Locale, String> nameDict2 = new HashMap<Locale, String>() {{
+ put(Locale.US, "TestService1");
+ }};
+ StreamingServiceInfo info1 = new StreamingServiceInfo(nameDict1, "Class 1", Locale.US,
+ "Service ID 1", new Date(System.currentTimeMillis() - 10000),
+ new Date(System.currentTimeMillis() + 10000));
+ StreamingServiceInfo info2 = new StreamingServiceInfo(nameDict2, "Class 2", Locale.US,
+ "Service ID 2", new Date(System.currentTimeMillis() - 20000),
+ new Date(System.currentTimeMillis() + 20000));
+ List<StreamingServiceInfo> serviceInfos = new LinkedList<StreamingServiceInfo>() {{
+ add(info1);
+ add(info2);
+ }};
+
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = appKey;
+ args.arg2 = serviceInfos;
+
+ mHandler.removeMessages(SEND_STREAMING_SERVICES_LIST);
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(SEND_STREAMING_SERVICES_LIST, args), 300);
+ return MbmsException.SUCCESS;
+ }
+ };
@Override
public void onDestroy() {
super.onCreate();
+ mHandlerThread.quitSafely();
logd("EmbmsTestStreamingService onDestroy");
}
@Override
public IBinder onBind(Intent intent) {
+ logd("EmbmsTestStreamingService onBind");
+ mHandlerThread = new HandlerThread("EmbmsTestStreamingServiceWorker");
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper(), mWorkerCallback);
return mBinder;
}
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamingAppIdentifier.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamingAppIdentifier.java
new file mode 100644
index 0000000..7cbb14a
--- /dev/null
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamingAppIdentifier.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.phone.testapps.embmsmw;
+
+public class StreamingAppIdentifier {
+ private final int uid;
+ private final String appName;
+ private final int subscriptionId;
+
+ public StreamingAppIdentifier(int uid, String appName, int subscriptionId) {
+ this.uid = uid;
+ this.appName = appName;
+ this.subscriptionId = subscriptionId;
+ }
+
+ public int getUid() {
+ return uid;
+ }
+
+ public String getAppName() {
+ return appName;
+ }
+
+ public int getSubscriptionId() {
+ return subscriptionId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ StreamingAppIdentifier that = (StreamingAppIdentifier) o;
+
+ if (uid != that.uid) {
+ return false;
+ }
+ if (subscriptionId != that.subscriptionId) {
+ return false;
+ }
+ return appName.equals(that.appName);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = uid;
+ result = 31 * result + (appName != null ? appName.hashCode() : 0);
+ result = 31 * result + subscriptionId;
+ return result;
+ }
+}
diff --git a/testapps/EmbmsTestStreamingApp/res/layout/activity_main.xml b/testapps/EmbmsTestStreamingApp/res/layout/activity_main.xml
index 866e127..028c443 100644
--- a/testapps/EmbmsTestStreamingApp/res/layout/activity_main.xml
+++ b/testapps/EmbmsTestStreamingApp/res/layout/activity_main.xml
@@ -20,9 +20,30 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
- <Button
- android:id="@+id/bind_button"
- android:layout_width="wrap_content"
+ <TextView
+ android:id="@+id/curr_streaming_uri"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/bind_button" />
+ android:label="@string/streaming_uri_label"/>
+ <GridLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+ <Button
+ android:id="@+id/bind_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bind_button" />
+ <Button
+ android:id="@+id/get_streaming_services_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/get_streaming_services_button" />
+ </GridLayout>
+ <Spinner
+ android:id="@+id/available_streaming_services"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:label="@string/available_streaming_services_label"/>
</LinearLayout>
diff --git a/testapps/EmbmsTestStreamingApp/res/values/donottranslate_strings.xml b/testapps/EmbmsTestStreamingApp/res/values/donottranslate_strings.xml
index 71808fa..4895b2d 100644
--- a/testapps/EmbmsTestStreamingApp/res/values/donottranslate_strings.xml
+++ b/testapps/EmbmsTestStreamingApp/res/values/donottranslate_strings.xml
@@ -17,4 +17,7 @@
<resources>
<string name="bind_button">Bind to service</string>
+ <string name="streaming_uri_label">Current Streaming URI</string>
+ <string name="get_streaming_services_button">Get streaming services</string>
+ <string name="available_streaming_services_label">Available Streaming Services</string>
</resources>
\ No newline at end of file
diff --git a/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/EmbmsTestStreamingApp.java b/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/EmbmsTestStreamingApp.java
index ed4fb6b..8369fde 100644
--- a/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/EmbmsTestStreamingApp.java
+++ b/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/EmbmsTestStreamingApp.java
@@ -17,21 +17,79 @@
package com.android.phone.testapps.embmsfrontend;
import android.app.Activity;
+import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.telephony.MbmsStreamingManager;
import android.telephony.mbms.MbmsException;
import android.telephony.mbms.MbmsStreamingManagerCallback;
+import android.telephony.mbms.StreamingServiceInfo;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
import android.widget.Button;
+import android.widget.Spinner;
+import android.widget.TextView;
import android.widget.Toast;
+import java.util.List;
+
public class EmbmsTestStreamingApp extends Activity {
- private MbmsStreamingManagerCallback mStreamingListener = new MbmsStreamingManagerCallback() {};
- private MbmsStreamingManager mStreamingManager;
+ private static final String APP_NAME = "StreamingApp1";
+
+ private MbmsStreamingManagerCallback mStreamingListener = new MbmsStreamingManagerCallback() {
+ @Override
+ public void streamingServicesUpdated(List<StreamingServiceInfo> services) {
+ EmbmsTestStreamingApp.this.runOnUiThread(() ->
+ Toast.makeText(EmbmsTestStreamingApp.this,
+ "Got services length " + services.size(),
+ Toast.LENGTH_SHORT).show());
+ updateStreamingServicesList(services);
+ }
+ };
+
+ private final class StreamingServiceInfoAdapter
+ extends ArrayAdapter<StreamingServiceInfo> {
+ public StreamingServiceInfoAdapter(Context context, int resource) {
+ super(context, resource);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ StreamingServiceInfo info = getItem(position);
+ TextView result = new TextView(EmbmsTestStreamingApp.this);
+ result.setText(info.getClassName());
+ return result;
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ StreamingServiceInfo info = getItem(position);
+ TextView result = new TextView(EmbmsTestStreamingApp.this);
+ String text = "classname="
+ + info.getClassName()
+ + ", "
+ + "serviceId="
+ + info.getServiceId();
+ result.setText(text);
+ return result;
+ }
+
+ public void update(List<StreamingServiceInfo> services) {
+ clear();
+ addAll(services);
+ }
+ }
+
+ private MbmsStreamingManager mStreamingManager = null;
private Handler mHandler;
private HandlerThread mHandlerThread;
+
+ private StreamingServiceInfoAdapter mStreamingServicesDisplayAdapter;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -40,13 +98,15 @@
mHandlerThread = new HandlerThread("EmbmsSampleFrontendWorker");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
+ mStreamingServicesDisplayAdapter =
+ new StreamingServiceInfoAdapter(this, android.R.layout.simple_spinner_item);
Button bindButton = (Button) findViewById(R.id.bind_button);
bindButton.setOnClickListener((view) ->
mHandler.post(() -> {
try {
mStreamingManager = MbmsStreamingManager.create(
- EmbmsTestStreamingApp.this, mStreamingListener, getPackageName());
+ EmbmsTestStreamingApp.this, mStreamingListener, APP_NAME);
} catch (MbmsException e) {
EmbmsTestStreamingApp.this.runOnUiThread(() ->
Toast.makeText(EmbmsTestStreamingApp.this,
@@ -58,6 +118,43 @@
Toast.LENGTH_SHORT).show());
})
);
+
+ Button getStreamingServicesButton = (Button)
+ findViewById(R.id.get_streaming_services_button);
+ getStreamingServicesButton.setOnClickListener((view) -> {
+ if (mStreamingManager == null) {
+ Toast.makeText(EmbmsTestStreamingApp.this,
+ "No streaming service bound", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ try {
+ mStreamingManager.getStreamingServices(null);
+ } catch (MbmsException e) {
+ Toast.makeText(EmbmsTestStreamingApp.this,
+ "Error getting streaming services" + e.getErrorCode(),
+ Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ Spinner serviceSelector = (Spinner) findViewById(R.id.available_streaming_services);
+ mStreamingServicesDisplayAdapter.setDropDownViewResource(
+ android.R.layout.simple_spinner_dropdown_item);
+ serviceSelector.setAdapter(mStreamingServicesDisplayAdapter);
+ serviceSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ StreamingServiceInfo info =
+ (StreamingServiceInfo) serviceSelector.getItemAtPosition(position);
+ Toast.makeText(EmbmsTestStreamingApp.this,
+ "Service selected: " + info.getClassName(), Toast.LENGTH_SHORT).show();
+ // TODO: use this value for start streaming
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+
+ }
+ });
}
@Override
@@ -65,4 +162,8 @@
super.onDestroy();
mHandlerThread.quit();
}
+
+ private void updateStreamingServicesList(List<StreamingServiceInfo> services) {
+ runOnUiThread(() -> mStreamingServicesDisplayAdapter.update(services));
+ }
}