OSDN Git Service

Changes to MbmsStreamingManager for test app
authorHall Liu <hallliu@google.com>
Thu, 27 Apr 2017 20:20:09 +0000 (13:20 -0700)
committerHall Liu <hallliu@google.com>
Fri, 5 May 2017 22:43:03 +0000 (15:43 -0700)
Add binding methods to MbmsStreamingManager
Add constants for synchronous binding exceptions

Test: testapp
Change-Id: Ie798c6008029c4201ec1bb3c98c11c4a949a048a

telephony/java/android/telephony/MbmsDownloadManager.java
telephony/java/android/telephony/MbmsStreamingManager.java
telephony/java/android/telephony/mbms/MbmsException.java [moved from telephony/java/android/telephony/mbms/MbmsInitializationException.java with 60% similarity]

index 862c919..d9f8fa6 100644 (file)
@@ -23,7 +23,7 @@ import android.telephony.mbms.DownloadCallback;
 import android.telephony.mbms.DownloadRequest;
 import android.telephony.mbms.DownloadStatus;
 import android.telephony.mbms.IMbmsDownloadManagerCallback;
-import android.telephony.mbms.MbmsInitializationException;
+import android.telephony.mbms.MbmsException;
 import android.telephony.mbms.vendor.IMbmsDownloadService;
 import android.util.Log;
 
@@ -172,7 +172,7 @@ public class MbmsDownloadManager {
      */
     public static MbmsDownloadManager createManager(Context context,
             IMbmsDownloadManagerCallback listener, String downloadAppName)
-            throws MbmsInitializationException{
+            throws MbmsException {
         MbmsDownloadManager mdm = new MbmsDownloadManager(context, listener, downloadAppName,
                 SubscriptionManager.getDefaultSubscriptionId());
         mdm.bindAndInitialize();
@@ -190,19 +190,19 @@ public class MbmsDownloadManager {
 
     public static MbmsDownloadManager createManager(Context context,
             IMbmsDownloadManagerCallback listener, String downloadAppName, int subId)
-            throws MbmsInitializationException {
+            throws MbmsException {
         MbmsDownloadManager mdm = new MbmsDownloadManager(context, listener, downloadAppName,
                 subId);
         mdm.bindAndInitialize();
         return mdm;
     }
 
-    private void bindAndInitialize() throws MbmsInitializationException {
+    private void bindAndInitialize() throws MbmsException {
         // TODO: bind
         try {
             mService.initialize(mDownloadAppName, mSubId, mCallback);
         } catch (RemoteException e) {
-            throw new MbmsInitializationException(0); // TODO: proper error code
+            throw new MbmsException(0); // TODO: proper error code
         }
     }
 
index 770a04a..fc406ee 100644 (file)
 
 package android.telephony;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.DeadObjectException;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.telephony.mbms.IMbmsStreamingManagerCallback;
 import android.telephony.mbms.IStreamingServiceCallback;
-import android.telephony.mbms.MbmsInitializationException;
+import android.telephony.mbms.MbmsException;
 import android.telephony.mbms.StreamingService;
 import android.telephony.mbms.StreamingServiceInfo;
 import android.telephony.mbms.vendor.IMbmsStreamingService;
 import android.util.Log;
 
+import java.util.LinkedList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 /** @hide */
 public class MbmsStreamingManager {
+    private interface ServiceListener {
+        void onServiceConnected();
+        void onServiceDisconnected();
+    }
+
     private static final String LOG_TAG = "MbmsStreamingManager";
+    public static final String MBMS_STREAMING_SERVICE_ACTION =
+            "android.telephony.action.EmbmsStreaming";
+
     private static final boolean DEBUG = true;
+    private static final int BIND_TIMEOUT_MS = 3000;
+
     private IMbmsStreamingService mService;
+    private ServiceConnection mServiceConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (service != null) {
+                Log.i(LOG_TAG, String.format("Connected to service %s", name));
+                synchronized (MbmsStreamingManager.this) {
+                    mService = IMbmsStreamingService.Stub.asInterface(service);
+                    mServiceListeners.forEach(ServiceListener::onServiceConnected);
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            Log.i(LOG_TAG, String.format("Disconnected from service %s", name));
+            synchronized (MbmsStreamingManager.this) {
+                mService = null;
+                mServiceListeners.forEach(ServiceListener::onServiceDisconnected);
+            }
+        }
+    };
+    private List<ServiceListener> mServiceListeners = new LinkedList<>();
+
     private IMbmsStreamingManagerCallback mCallbackToApp;
     private final String mAppName;
 
@@ -54,9 +97,8 @@ public class MbmsStreamingManager {
      * Create a new MbmsStreamingManager using the given subscription ID.
      *
      * Note that this call will bind a remote service and that may take a bit.  This
-     * may throw an IllegalArgumentException or RemoteException.
-     * TODO: document this and add exceptions that can be thrown for synchronous
-     * initialization/bind errors
+     * may throw an {@link MbmsException}, indicating errors that may happen during
+     * the initialization or binding process.
      *
      * @param context
      * @param listener
@@ -66,7 +108,7 @@ public class MbmsStreamingManager {
      */
     public static MbmsStreamingManager create(Context context,
             IMbmsStreamingManagerCallback listener, String streamingAppName, int subscriptionId)
-            throws MbmsInitializationException {
+            throws MbmsException {
         MbmsStreamingManager manager = new MbmsStreamingManager(context, listener,
                 streamingAppName, subscriptionId);
         manager.bindAndInitialize();
@@ -81,9 +123,8 @@ public class MbmsStreamingManager {
      */
     public static MbmsStreamingManager create(Context context,
             IMbmsStreamingManagerCallback listener, String streamingAppName)
-            throws MbmsInitializationException {
-        // TODO: get default sub id
-        int subId = INVALID_SUBSCRIPTION_ID;
+            throws MbmsException {
+        int subId = SubscriptionManager.getDefaultSubscriptionId();
         MbmsStreamingManager manager = new MbmsStreamingManager(context, listener,
                 streamingAppName, subId);
         manager.bindAndInitialize();
@@ -94,8 +135,17 @@ public class MbmsStreamingManager {
      * Terminates this instance, ending calls to the registered listener.  Also terminates
      * any streaming services spawned from this instance.
      */
-    public void dispose() {
-        // service.dispose(streamingAppName);
+    public synchronized void dispose() {
+        if (mService == null) {
+            // Ignore and return, assume already disposed.
+            return;
+        }
+        try {
+            mService.dispose(mAppName, mSubscriptionId);
+        } catch (RemoteException e) {
+            // Ignore for now
+        }
+        mService = null;
     }
 
     /**
@@ -155,23 +205,79 @@ public class MbmsStreamingManager {
         return 0;
     }
 
-    private void logd(String str) {
-        Log.d(LOG_TAG, str);
-    }
+    private void bindAndInitialize() throws MbmsException {
+        // Query for the proper service
+        PackageManager packageManager = mContext.getPackageManager();
+        Intent queryIntent = new Intent();
+        queryIntent.setAction(MBMS_STREAMING_SERVICE_ACTION);
+        List<ResolveInfo> streamingServices = packageManager.queryIntentServices(queryIntent,
+                PackageManager.MATCH_SYSTEM_ONLY);
+
+        if (streamingServices == null || streamingServices.size() == 0) {
+            throw new MbmsException(
+                    MbmsException.ERROR_NO_SERVICE_INSTALLED);
+        }
+        if (streamingServices.size() > 1) {
+            throw new MbmsException(
+                    MbmsException.ERROR_MULTIPLE_SERVICES_INSTALLED);
+        }
+
+        // Kick off the binding, and synchronously wait until binding is complete
+        final CountDownLatch latch = new CountDownLatch(1);
+        ServiceListener bindListener = new ServiceListener() {
+            @Override
+            public void onServiceConnected() {
+                latch.countDown();
+            }
+
+            @Override
+            public void onServiceDisconnected() {
+            }
+        };
+
+        synchronized (this) {
+            mServiceListeners.add(bindListener);
+        }
+
+        Intent bindIntent = new Intent();
+        bindIntent.setComponent(streamingServices.get(0).getComponentInfo().getComponentName());
+
+        mContext.bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
 
-    private boolean isServiceConnected() {
-        return mService != null;
+        waitOnLatchWithTimeout(latch, BIND_TIMEOUT_MS);
+
+        // Remove the listener and call the initialization method through the interface.
+        synchronized (this) {
+            mServiceListeners.remove(bindListener);
+
+            if (mService == null) {
+                throw new MbmsException(MbmsException.ERROR_BIND_TIMEOUT_OR_FAILURE);
+            }
+
+            try {
+                int returnCode = mService.initialize(mCallbackToApp, mAppName, mSubscriptionId);
+                if (returnCode != MbmsException.SUCCESS) {
+                    throw new MbmsException(returnCode);
+                }
+            } catch (RemoteException e) {
+                mService = null;
+                Log.e(LOG_TAG, "Service died before initialization");
+                throw new MbmsException(MbmsException.ERROR_INITIALIZATION_REMOTE_EXCEPTION);
+            }
+        }
     }
 
-    private void bindAndInitialize() throws MbmsInitializationException {
-        // TODO: bind to the service
-        try {
-            int returnCode = mService.initialize(mCallbackToApp, mAppName, mSubscriptionId);
-            if (returnCode != 0) {
-                throw new MbmsInitializationException(returnCode);
+    private static void waitOnLatchWithTimeout(CountDownLatch l, long timeoutMs) {
+        long endTime = System.currentTimeMillis() + timeoutMs;
+        while (System.currentTimeMillis() < endTime) {
+            try {
+                l.await(timeoutMs, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                // keep waiting
+            }
+            if (l.getCount() <= 0) {
+                return;
             }
-        } catch (RemoteException e) {
-            throw new MbmsInitializationException(/* some error */ 0);
         }
     }
 }
 
 package android.telephony.mbms;
 
+import android.os.RemoteException;
+
 /** @hide */
-public class MbmsInitializationException extends Exception {
+public class MbmsException extends RemoteException {
+    public static final int SUCCESS = 0;
+    public static final int ERROR_NO_SERVICE_INSTALLED = 1;
+    public static final int ERROR_MULTIPLE_SERVICES_INSTALLED = 2;
+    public static final int ERROR_BIND_TIMEOUT_OR_FAILURE = 3;
+    public static final int ERROR_INITIALIZATION_REMOTE_EXCEPTION = 4;
+    public static final int ERROR_ALREADY_INITIALIZED = 5;
+
     private final int mErrorCode;
 
-    /** @hide */
-    public MbmsInitializationException(int errorCode) {
+    /** @hide
+     * TODO: future systemapi
+     * */
+    public MbmsException(int errorCode) {
         super();
         mErrorCode = errorCode;
     }