Merge "Implement stopStreaming API for MBMS"
diff --git a/telephony/java/android/telephony/MbmsStreamingManager.java b/telephony/java/android/telephony/MbmsStreamingManager.java
index 251d5bb..6754426 100644
--- a/telephony/java/android/telephony/MbmsStreamingManager.java
+++ b/telephony/java/android/telephony/MbmsStreamingManager.java
@@ -22,6 +22,7 @@
 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.MbmsException;
@@ -157,6 +158,7 @@
      * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
      * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
      * {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
+     * {@link MbmsException#ERROR_SERVICE_LOST}
      *
      * Asynchronous error codes via the {@link MbmsStreamingManagerCallback#error(int, String)}
      * callback can include any of the errors except:
@@ -172,6 +174,10 @@
             if (returnCode != MbmsException.SUCCESS) {
                 throw new MbmsException(returnCode);
             }
+        } catch (DeadObjectException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService = null;
+            throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
         } catch (RemoteException e) {
             throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
         }
@@ -187,6 +193,7 @@
      * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
      * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
      * {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
+     * {@link MbmsException#ERROR_SERVICE_LOST}
      *
      * May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
      *
@@ -204,6 +211,10 @@
             if (returnCode != MbmsException.SUCCESS) {
                 throw new MbmsException(returnCode);
             }
+        } catch (DeadObjectException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService = null;
+            throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
         } catch (RemoteException e) {
             throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
         }
@@ -269,7 +280,11 @@
             } catch (RemoteException e) {
                 mService = null;
                 Log.e(LOG_TAG, "Service died before initialization");
-                throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+                if (e instanceof DeadObjectException) {
+                    throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
+                } else {
+                    throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+                }
             }
         }
     }
diff --git a/telephony/java/android/telephony/mbms/MbmsException.java b/telephony/java/android/telephony/mbms/MbmsException.java
index a0ded9b..ac14c4f 100644
--- a/telephony/java/android/telephony/mbms/MbmsException.java
+++ b/telephony/java/android/telephony/mbms/MbmsException.java
@@ -29,6 +29,7 @@
     public static final int ERROR_UNABLE_TO_START_SERVICE = 8;
     public static final int ERROR_STREAM_ALREADY_STARTED = 9;
     public static final int ERROR_END_OF_SESSION = 10;
+    public static final int ERROR_SERVICE_LOST = 11;
 
     private final int mErrorCode;
 
diff --git a/telephony/java/android/telephony/mbms/StreamingService.java b/telephony/java/android/telephony/mbms/StreamingService.java
index ac5fbdf..745cb98 100644
--- a/telephony/java/android/telephony/mbms/StreamingService.java
+++ b/telephony/java/android/telephony/mbms/StreamingService.java
@@ -17,8 +17,7 @@
 package android.telephony.mbms;
 
 import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.DeadObjectException;
 import android.os.RemoteException;
 import android.telephony.mbms.vendor.IMbmsStreamingService;
 import android.util.Log;
@@ -34,9 +33,10 @@
 
     private final String mAppName;
     private final int mSubscriptionId;
-    private final IMbmsStreamingService mService;
     private final StreamingServiceInfo mServiceInfo;
     private final IStreamingServiceCallback mCallback;
+
+    private IMbmsStreamingService mService;
     /**
      * @hide
      */
@@ -55,13 +55,23 @@
     /**
      * Retreive the Uri used to play this stream.
      *
-     * This may throw a {@link MbmsException} with the error code
-     * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
+     * This may throw a {@link MbmsException} with the error codes
+     * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION} or
+     * {@link MbmsException#ERROR_SERVICE_LOST}
+     *
      * @return The {@link Uri} to pass to the streaming client.
      */
     public Uri getPlaybackUri() throws MbmsException {
+        if (mService == null) {
+            throw new IllegalStateException("No streaming service attached");
+        }
+
         try {
             return mService.getPlaybackUri(mAppName, mSubscriptionId, mServiceInfo.getServiceId());
+        } catch (DeadObjectException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService = null;
+            throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "Caught remote exception calling getPlaybackUri: " + e);
             throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
@@ -76,18 +86,41 @@
     }
 
     /**
-     * Stop streaming this service.  Terminal.
-     *
-     * This may throw a RemoteException.
+     * Stop streaming this service.
+     * This may throw a {@link MbmsException} with the error code
+     * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION} or
+     * {@link MbmsException#ERROR_SERVICE_LOST}
      */
-    public void stopStreaming() {
+    public void stopStreaming() throws MbmsException {
+        if (mService == null) {
+            throw new IllegalStateException("No streaming service attached");
+        }
+
+        try {
+            mService.stopStreaming(mAppName, mSubscriptionId, mServiceInfo.getServiceId());
+        } catch (DeadObjectException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService = null;
+            throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "Caught remote exception calling stopStreaming: " + e);
+            throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+        }
     }
 
     public void dispose() throws MbmsException {
+        if (mService == null) {
+            throw new IllegalStateException("No streaming service attached");
+        }
+
         try {
             mService.disposeStream(mAppName, mSubscriptionId, mServiceInfo.getServiceId());
+        } catch (DeadObjectException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService = null;
+            throw new MbmsException(MbmsException.ERROR_SERVICE_LOST);
         } catch (RemoteException e) {
-            Log.w(LOG_TAG, "Caught remote exception calling disposeStream: " + e);
+            Log.w(LOG_TAG, "Caught remote exception calling dispose: " + e);
             throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
         }
     }
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
index 37f47ff..5b74312 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
@@ -107,15 +107,44 @@
         return null;
     }
 
+    /**
+     * Stop streaming the stream identified by {@code serviceId}. Notification of the resulting
+     * stream state change should be reported to the app via
+     * {@link IStreamingServiceCallback#streamStateChanged(int)}.
+     * @param appName The app name as negotiated with the wireless carrier.
+     * @param subscriptionId The subscription id to use.
+     * @param serviceId The ID of the streaming service that the app wishes to stop.
+     */
     @Override
-    public void stopStreaming(String appName, int subId, String serviceId) throws RemoteException {
+    public void stopStreaming(String appName, int subscriptionId, String serviceId)
+            throws RemoteException {
     }
 
+    /**
+     * Dispose of the stream identified by {@code serviceId} for the app identified by the
+     * {@code appName} and {@code subscriptionId} arguments along with the caller's uid.
+     * No notification back to the app is required for this operation, and the callback provided via
+     * {@link #startStreaming(String, int, String, IStreamingServiceCallback)} should no longer be
+     * used after this method has called by the app.
+     * @param appName The app name as negotiated with the wireless carrier.
+     * @param subscriptionId The subscription id to use.
+     * @param serviceId The ID of the streaming service that the app wishes to dispose of.
+     */
     @Override
-    public void disposeStream(String appName, int subId, String serviceId) throws RemoteException {
+    public void disposeStream(String appName, int subscriptionId, String serviceId)
+            throws RemoteException {
     }
 
+    /**
+     * Signals that the app wishes to dispose of the session identified by the {@code appName} and
+     * {@code subscriptionId} arguments, as well as the caller's uid. No notification back to the
+     * app is required for this operation, and the corresponding callback provided via
+     * {@link #initialize(IMbmsStreamingManagerCallback, String, int)} should no longer be used
+     * after this method has been called by the app.
+     * @param appName The app name as negotiated with the wireless carrier.
+     * @param subscriptionId The subscription id to use.
+     */
     @Override
-    public void dispose(String appName, int subId) throws RemoteException {
+    public void dispose(String appName, int subscriptionId) throws RemoteException {
     }
 }