Implement Ims's VideoCallProvider, including a wrapper.
Andrew Lee [Fri, 8 Aug 2014 08:42:33 +0000 (01:42 -0700)]
+ Implements ConnectionService.VideoCallProvider as
ImsVideoCallProviderWrapper. ConnectionService treats this as
the concrete implementation of VideoCallProvider. In detail though,
it is a wrapper around ImsVideoCallProvider which should be extended
in ImsService and implements the actual video call provider
functionality. This wrapper intermediates communication for commands
sent through Telephony and carried out in ImsService. It also
implements the callback class whose binder is provided to the
ImsVideoCallProvider.
+ ImsVideoCallProvider is an abstract class which defines
functionality which satisfies ConnectionService.VideoCallProvider.
We don't directly extend VideoCallProvider because of the
inter-process communication necessary across Telephony and
ImsService. This class provides a binder which is passed to the
ImsVideoCallProviderWrapper.
+ Implement getVideoCallProvider on ImsCallSession.

Bug: 16886403
Change-Id: I9b995baa74149b3c046789f797ab0ff49ae7165b

src/java/com/android/ims/internal/ImsCallSession.java
src/java/com/android/ims/internal/ImsVideoCallProvider.java [new file with mode: 0644]
src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java [new file with mode: 0644]

index 4cbad16..4625ec2 100644 (file)
@@ -17,7 +17,6 @@
 package com.android.ims.internal;
 
 import android.os.RemoteException;
-import android.telephony.Rlog;
 
 import com.android.ims.ImsCallProfile;
 import com.android.ims.ImsConferenceState;
@@ -447,6 +446,23 @@ public class ImsCallSession {
     }
 
     /**
+     * Gets the video call provider for the session.
+     *
+     * @return The video call provider.
+     */
+    public IImsVideoCallProvider getVideoCallProvider() {
+        if (mClosed) {
+            return null;
+        }
+
+        try {
+            return miSession.getVideoCallProvider();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
      * Gets the value associated with the specified property of this session.
      *
      * @return the string value associated with the specified property
diff --git a/src/java/com/android/ims/internal/ImsVideoCallProvider.java b/src/java/com/android/ims/internal/ImsVideoCallProvider.java
new file mode 100644 (file)
index 0000000..01a8bbb
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2014 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.ims.internal;
+
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telecomm.CallCameraCapabilities;
+import android.telecomm.VideoCallProfile;
+import android.view.Surface;
+
+public abstract class ImsVideoCallProvider {
+    private static final int MSG_SET_CALLBACK = 1;
+    private static final int MSG_SET_CAMERA = 2;
+    private static final int MSG_SET_PREVIEW_SURFACE = 3;
+    private static final int MSG_SET_DISPLAY_SURFACE = 4;
+    private static final int MSG_SET_DEVICE_ORIENTATION = 5;
+    private static final int MSG_SET_ZOOM = 6;
+    private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7;
+    private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8;
+    private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9;
+    private static final int MSG_REQUEST_CALL_DATA_USAGE = 10;
+    private static final int MSG_SET_PAUSE_IMAGE = 11;
+
+    private final ImsVideoCallProviderBinder mBinder;
+
+    private IImsVideoCallCallback mCallback;
+
+    /**
+     * Default handler used to consolidate binder method calls onto a single thread.
+     */
+    private final Handler mProviderHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SET_CALLBACK:
+                    mCallback = (IImsVideoCallCallback) msg.obj;
+                    break;
+                case MSG_SET_CAMERA:
+                    onSetCamera((String) msg.obj);
+                    break;
+                case MSG_SET_PREVIEW_SURFACE:
+                    onSetPreviewSurface((Surface) msg.obj);
+                    break;
+                case MSG_SET_DISPLAY_SURFACE:
+                    onSetDisplaySurface((Surface) msg.obj);
+                    break;
+                case MSG_SET_DEVICE_ORIENTATION:
+                    onSetDeviceOrientation(msg.arg1);
+                    break;
+                case MSG_SET_ZOOM:
+                    onSetZoom((Float) msg.obj);
+                    break;
+                case MSG_SEND_SESSION_MODIFY_REQUEST:
+                    onSendSessionModifyRequest((VideoCallProfile) msg.obj);
+                    break;
+                case MSG_SEND_SESSION_MODIFY_RESPONSE:
+                    onSendSessionModifyResponse((VideoCallProfile) msg.obj);
+                    break;
+                case MSG_REQUEST_CAMERA_CAPABILITIES:
+                    onRequestCameraCapabilities();
+                    break;
+                case MSG_REQUEST_CALL_DATA_USAGE:
+                    onRequestCallDataUsage();
+                    break;
+                case MSG_SET_PAUSE_IMAGE:
+                    onSetPauseImage((String) msg.obj);
+                    break;
+                default:
+                    break;
+            }
+        }
+    };
+
+    /**
+     * IImsVideoCallProvider stub implementation.
+     */
+    private final class ImsVideoCallProviderBinder extends IImsVideoCallProvider.Stub {
+        public void setCallback(IImsVideoCallCallback callback) {
+            mProviderHandler.obtainMessage(MSG_SET_CALLBACK, callback).sendToTarget();
+        }
+
+        public void setCamera(String cameraId) {
+            mProviderHandler.obtainMessage(MSG_SET_CAMERA, cameraId).sendToTarget();
+        }
+
+        public void setPreviewSurface(Surface surface) {
+            mProviderHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget();
+        }
+
+        public void setDisplaySurface(Surface surface) {
+            mProviderHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget();
+        }
+
+        public void setDeviceOrientation(int rotation) {
+            mProviderHandler.obtainMessage(MSG_SET_DEVICE_ORIENTATION, rotation).sendToTarget();
+        }
+
+        public void setZoom(float value) {
+            mProviderHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget();
+        }
+
+        public void sendSessionModifyRequest(VideoCallProfile requestProfile) {
+            mProviderHandler.obtainMessage(
+                    MSG_SEND_SESSION_MODIFY_REQUEST, requestProfile).sendToTarget();
+        }
+
+        public void sendSessionModifyResponse(VideoCallProfile responseProfile) {
+            mProviderHandler.obtainMessage(
+                    MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget();
+        }
+
+        public void requestCameraCapabilities() {
+            mProviderHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget();
+        }
+
+        public void requestCallDataUsage() {
+            mProviderHandler.obtainMessage(MSG_REQUEST_CALL_DATA_USAGE).sendToTarget();
+        }
+
+        public void setPauseImage(String uri) {
+            mProviderHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget();
+        }
+    }
+
+    public ImsVideoCallProvider() {
+        mBinder = new ImsVideoCallProviderBinder();
+    }
+
+    /**
+     * Returns binder object which can be used across IPC methods.
+     */
+    public final IImsVideoCallProvider getInterface() {
+        return mBinder;
+    }
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onSetCamera */
+    public abstract void onSetCamera(String cameraId);
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onSetPreviewSurface */
+    public abstract void onSetPreviewSurface(Surface surface);
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onSetDisplaySurface */
+    public abstract void onSetDisplaySurface(Surface surface);
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onSetDeviceOrientation */
+    public abstract void onSetDeviceOrientation(int rotation);
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onSetZoom */
+    public abstract void onSetZoom(float value);
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onSendSessionModifyRequest */
+    public abstract void onSendSessionModifyRequest(VideoCallProfile requestProfile);
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onSendSessionModifyResponse */
+    public abstract void onSendSessionModifyResponse(VideoCallProfile responseProfile);
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onRequestCameraCapabilities */
+    public abstract void onRequestCameraCapabilities();
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onRequestCallDataUsage */
+    public abstract void onRequestCallDataUsage();
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#onSetPauseImage */
+    public abstract void onSetPauseImage(String uri);
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#receiveSessionModifyRequest */
+    public void receiveSessionModifyRequest(VideoCallProfile videoCallProfile) {
+        if (mCallback != null) {
+            try {
+                mCallback.receiveSessionModifyRequest(videoCallProfile);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#receiveSessionModifyResponse */
+    public void receiveSessionModifyResponse(
+            int status, VideoCallProfile requestedProfile, VideoCallProfile responseProfile) {
+        if (mCallback != null) {
+            try {
+                mCallback.receiveSessionModifyResponse(status, requestedProfile, responseProfile);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#handleCallSessionEvent */
+    public void handleCallSessionEvent(int event) {
+        if (mCallback != null) {
+            try {
+                mCallback.handleCallSessionEvent(event);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#changePeerDimensions */
+    public void changePeerDimensions(int width, int height) {
+        if (mCallback != null) {
+            try {
+                mCallback.changePeerDimensions(width, height);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#changeCallDataUsage */
+    public void changeCallDataUsage(int dataUsage) {
+        if (mCallback != null) {
+            try {
+                mCallback.changeCallDataUsage(dataUsage);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see android.telecomm.ConnectionService.VideoCallProvider#changeCameraCapabilities */
+    public void changeCameraCapabilities(CallCameraCapabilities callCameraCapabilities) {
+        if (mCallback != null) {
+            try {
+                mCallback.changeCameraCapabilities(callCameraCapabilities);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java b/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java
new file mode 100644 (file)
index 0000000..4edb311
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2014 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.ims.internal;
+
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telecomm.CallCameraCapabilities;
+import android.telecomm.ConnectionService;
+import android.telecomm.VideoCallProfile;
+import android.view.Surface;
+
+import com.android.internal.os.SomeArgs;
+
+import java.lang.RuntimeException;
+
+/**
+ * Subclass implementation of {@link ConnectionService.VideoCallProvider}. This intermediates and
+ * communicates with the actual implementation of the video call provider in the IMS service; it is
+ * in essence, a wrapper around the IMS's video call provider implementation.
+ *
+ * This class maintains a binder by which the ImsVideoCallProvider's implementation can communicate
+ * its intent to invoke callbacks. In this class, the message across this binder is handled, and
+ * the superclass's methods are used to execute the callbacks.
+ *
+ * @hide
+ */
+public class ImsVideoCallProviderWrapper extends ConnectionService.VideoCallProvider {
+    private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
+    private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
+    private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
+    private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
+    private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
+    private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
+
+    private final IImsVideoCallProvider mVideoCallProvider;
+    private final ImsVideoCallCallback mBinder;
+
+    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            mVideoCallProvider.asBinder().unlinkToDeath(this, 0);
+        }
+    };
+
+    /**
+     * IImsVideoCallCallback stub implementation.
+     */
+    private final class ImsVideoCallCallback extends IImsVideoCallCallback.Stub {
+        @Override
+        public void receiveSessionModifyRequest(VideoCallProfile videoCallProfile) {
+            mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_REQUEST,
+                    videoCallProfile).sendToTarget();
+        }
+
+        @Override
+        public void receiveSessionModifyResponse(
+                int status, VideoCallProfile requestProfile, VideoCallProfile responseProfile) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = status;
+            args.arg2 = requestProfile;
+            args.arg3 = responseProfile;
+            mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args).sendToTarget();
+        }
+
+        @Override
+        public void handleCallSessionEvent(int event) {
+            mHandler.obtainMessage(MSG_HANDLE_CALL_SESSION_EVENT, event).sendToTarget();
+        }
+
+        @Override
+        public void changePeerDimensions(int width, int height) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = width;
+            args.arg2 = height;
+            mHandler.obtainMessage(MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
+        }
+
+        @Override
+        public void changeCallDataUsage(int dataUsage) {
+            mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, dataUsage).sendToTarget();
+        }
+
+        @Override
+        public void changeCameraCapabilities(CallCameraCapabilities cameraCapabilities) {
+            mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES,
+                    cameraCapabilities).sendToTarget();
+        }
+    }
+
+    /** Default handler used to consolidate binder method calls onto a single thread. */
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            SomeArgs args;
+            switch (msg.what) {
+                case MSG_RECEIVE_SESSION_MODIFY_REQUEST:
+                    receiveSessionModifyRequest((VideoCallProfile) msg.obj);
+                    break;
+                case MSG_RECEIVE_SESSION_MODIFY_RESPONSE:
+                    args = (SomeArgs) msg.obj;
+                    try {
+                        int status = (int) args.arg1;
+                        VideoCallProfile requestProfile = (VideoCallProfile) args.arg2;
+                        VideoCallProfile responseProfile = (VideoCallProfile) args.arg3;
+
+                        receiveSessionModifyResponse(status, requestProfile, responseProfile);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                case MSG_HANDLE_CALL_SESSION_EVENT:
+                    handleCallSessionEvent((int) msg.obj);
+                    break;
+                case MSG_CHANGE_PEER_DIMENSIONS:
+                    args = (SomeArgs) msg.obj;
+                    try {
+                        int width = (int) args.arg1;
+                        int height = (int) args.arg2;
+                        changePeerDimensions(width, height);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                case MSG_CHANGE_CALL_DATA_USAGE:
+                    changeCallDataUsage(msg.arg1);
+                    break;
+                case MSG_CHANGE_CAMERA_CAPABILITIES:
+                    changeCameraCapabilities((CallCameraCapabilities) msg.obj);
+                    break;
+                default:
+                    break;
+            }
+        }
+    };
+
+    /**
+     * Instantiates an instance of the ImsVideoCallProvider, taking in the binder for IMS's video
+     * call provider implementation.
+     *
+     * @param videoCallProvider
+     */
+    public ImsVideoCallProviderWrapper(IImsVideoCallProvider videoCallProvider)
+            throws RemoteException {
+        mVideoCallProvider = videoCallProvider;
+        mVideoCallProvider.asBinder().linkToDeath(mDeathRecipient, 0);
+
+        mBinder = new ImsVideoCallCallback();
+        mVideoCallProvider.setCallback(mBinder);
+    }
+
+    /** @inheritDoc */
+    public void onSetCamera(String cameraId) {
+        try {
+            mVideoCallProvider.setCamera(cameraId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onSetPreviewSurface(Surface surface) {
+        try {
+            mVideoCallProvider.setPreviewSurface(surface);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onSetDisplaySurface(Surface surface) {
+        try {
+            mVideoCallProvider.setDisplaySurface(surface);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onSetDeviceOrientation(int rotation) {
+        try {
+            mVideoCallProvider.setDeviceOrientation(rotation);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onSetZoom(float value) {
+        try {
+            mVideoCallProvider.setZoom(value);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onSendSessionModifyRequest(VideoCallProfile requestProfile) {
+        try {
+            mVideoCallProvider.sendSessionModifyRequest(requestProfile);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onSendSessionModifyResponse(VideoCallProfile responseProfile) {
+        try {
+            mVideoCallProvider.sendSessionModifyResponse(responseProfile);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onRequestCameraCapabilities() {
+        try {
+            mVideoCallProvider.requestCameraCapabilities();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onRequestCallDataUsage() {
+        try {
+            mVideoCallProvider.requestCallDataUsage();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** @inheritDoc */
+    public void onSetPauseImage(String uri) {
+        try {
+            mVideoCallProvider.setPauseImage(uri);
+        } catch (RemoteException e) {
+        }
+    }
+}
\ No newline at end of file