diff options
| -rw-r--r-- | api/current.txt | 6 | ||||
| -rw-r--r-- | api/system-current.txt | 6 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/Call.java | 139 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/CallbackRecord.java | 44 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/InCallService.java | 13 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/Phone.java | 4 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/RemoteConference.java | 112 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/RemoteConnection.java | 244 | ||||
| -rw-r--r-- | telecomm/java/android/telecom/VideoCallImpl.java | 62 | 
9 files changed, 507 insertions, 123 deletions
diff --git a/api/current.txt b/api/current.txt index be011123e549..b41493a9ad7e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -30257,6 +30257,7 @@ package android.telecom {      method public void playDtmfTone(char);      method public void postDialContinue(boolean);      method public void registerCallback(android.telecom.Call.Callback); +    method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);      method public void reject(boolean, java.lang.String);      method public void splitFromConference();      method public void stopDtmfTone(); @@ -30564,6 +30565,7 @@ package android.telecom {    public static abstract class InCallService.VideoCall {      ctor public InCallService.VideoCall();      method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback); +    method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback, android.os.Handler);      method public abstract void requestCallDataUsage();      method public abstract void requestCameraCapabilities();      method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile); @@ -30574,7 +30576,7 @@ package android.telecom {      method public abstract void setPauseImage(java.lang.String);      method public abstract void setPreviewSurface(android.view.Surface);      method public abstract void setZoom(float); -    method public abstract void unregisterCallback(); +    method public abstract void unregisterCallback(android.telecom.InCallService.VideoCall.Callback);    }    public static abstract class InCallService.VideoCall.Callback { @@ -30662,6 +30664,7 @@ package android.telecom {      method public void merge();      method public void playDtmfTone(char);      method public final void registerCallback(android.telecom.RemoteConference.Callback); +    method public final void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler);      method public void separate(android.telecom.RemoteConnection);      method public void setAudioState(android.telecom.AudioState);      method public void stopDtmfTone(); @@ -30701,6 +30704,7 @@ package android.telecom {      method public void playDtmfTone(char);      method public void postDialContinue(boolean);      method public void registerCallback(android.telecom.RemoteConnection.Callback); +    method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);      method public void reject();      method public void setAudioState(android.telecom.AudioState);      method public void stopDtmfTone(); diff --git a/api/system-current.txt b/api/system-current.txt index c4f96afed355..09411dbfeb04 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -32371,6 +32371,7 @@ package android.telecom {      method public void playDtmfTone(char);      method public void postDialContinue(boolean);      method public void registerCallback(android.telecom.Call.Callback); +    method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);      method public void reject(boolean, java.lang.String);      method public deprecated void removeListener(android.telecom.Call.Listener);      method public void splitFromConference(); @@ -32687,6 +32688,7 @@ package android.telecom {    public static abstract class InCallService.VideoCall {      ctor public InCallService.VideoCall();      method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback); +    method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback, android.os.Handler);      method public abstract void requestCallDataUsage();      method public abstract void requestCameraCapabilities();      method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile); @@ -32697,7 +32699,7 @@ package android.telecom {      method public abstract void setPauseImage(java.lang.String);      method public abstract void setPreviewSurface(android.view.Surface);      method public abstract void setZoom(float); -    method public abstract void unregisterCallback(); +    method public abstract void unregisterCallback(android.telecom.InCallService.VideoCall.Callback);    }    public static abstract class InCallService.VideoCall.Callback { @@ -32805,6 +32807,7 @@ package android.telecom {      method public void merge();      method public void playDtmfTone(char);      method public final void registerCallback(android.telecom.RemoteConference.Callback); +    method public final void registerCallback(android.telecom.RemoteConference.Callback, android.os.Handler);      method public void separate(android.telecom.RemoteConnection);      method public void setAudioState(android.telecom.AudioState);      method public void stopDtmfTone(); @@ -32844,6 +32847,7 @@ package android.telecom {      method public void playDtmfTone(char);      method public void postDialContinue(boolean);      method public void registerCallback(android.telecom.RemoteConnection.Callback); +    method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);      method public void reject();      method public void setAudioState(android.telecom.AudioState);      method public void stopDtmfTone(); diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index d92c0c7d0ba1..9273939b8cc4 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -19,10 +19,12 @@ package android.telecom;  import android.annotation.SystemApi;  import android.net.Uri;  import android.os.Bundle; +import android.os.Handler;  import java.lang.String;  import java.util.ArrayList;  import java.util.Collections; +import java.util.LinkedList;  import java.util.List;  import java.util.Map;  import java.util.Objects; @@ -608,7 +610,7 @@ public final class Call {      private final List<String> mChildrenIds = new ArrayList<>();      private final List<Call> mChildren = new ArrayList<>();      private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren); -    private final List<Callback> mCallbacks = new CopyOnWriteArrayList<>(); +    private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();      private final List<Call> mConferenceableCalls = new ArrayList<>();      private final List<Call> mUnmodifiableConferenceableCalls =              Collections.unmodifiableList(mConferenceableCalls); @@ -850,7 +852,20 @@ public final class Call {       * @param callback A {@code Callback}.       */      public void registerCallback(Callback callback) { -        mCallbacks.add(callback); +        registerCallback(callback, new Handler()); +    } + +    /** +     * Registers a callback to this {@code Call}. +     * +     * @param callback A {@code Callback}. +     * @param handler A handler which command and status changes will be delivered to. +     */ +    public void registerCallback(Callback callback, Handler handler) { +        unregisterCallback(callback); +        if (callback != null && handler != null) { +            mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler)); +        }      }      /** @@ -860,7 +875,12 @@ public final class Call {       */      public void unregisterCallback(Callback callback) {          if (callback != null) { -            mCallbacks.remove(callback); +            for (CallbackRecord<Callback> record : mCallbackRecords) { +                if (record.getCallback() == callback) { +                    mCallbackRecords.remove(record); +                    break; +                } +            }          }      } @@ -1021,57 +1041,120 @@ public final class Call {          }      } -    private void fireStateChanged(int newState) { -        for (Callback callback : mCallbacks) { -            callback.onStateChanged(this, newState); +    private void fireStateChanged(final int newState) { +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onStateChanged(call, newState); +                } +            });          }      } -    private void fireParentChanged(Call newParent) { -        for (Callback callback : mCallbacks) { -            callback.onParentChanged(this, newParent); +    private void fireParentChanged(final Call newParent) { +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onParentChanged(call, newParent); +                } +            });          }      } -    private void fireChildrenChanged(List<Call> children) { -        for (Callback callback : mCallbacks) { -            callback.onChildrenChanged(this, children); +    private void fireChildrenChanged(final List<Call> children) { +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onChildrenChanged(call, children); +                } +            });          }      } -    private void fireDetailsChanged(Details details) { -        for (Callback callback : mCallbacks) { -            callback.onDetailsChanged(this, details); +    private void fireDetailsChanged(final Details details) { +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onDetailsChanged(call, details); +                } +            });          }      } -    private void fireCannedTextResponsesLoaded(List<String> cannedTextResponses) { -        for (Callback callback : mCallbacks) { -            callback.onCannedTextResponsesLoaded(this, cannedTextResponses); +    private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) { +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onCannedTextResponsesLoaded(call, cannedTextResponses); +                } +            });          }      } -    private void fireVideoCallChanged(InCallService.VideoCall videoCall) { -        for (Callback callback : mCallbacks) { -            callback.onVideoCallChanged(this, videoCall); +    private void fireVideoCallChanged(final InCallService.VideoCall videoCall) { +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onVideoCallChanged(call, videoCall); +                } +            });          }      } -    private void firePostDialWait(String remainingPostDialSequence) { -        for (Callback callback : mCallbacks) { -            callback.onPostDialWait(this, remainingPostDialSequence); +    private void firePostDialWait(final String remainingPostDialSequence) { +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onPostDialWait(call, remainingPostDialSequence); +                } +            });          }      }      private void fireCallDestroyed() { -        for (Callback callback : mCallbacks) { -            callback.onCallDestroyed(this); +        for (CallbackRecord<Callback> record: mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onCallDestroyed(call); +                } +            });          }      }      private void fireConferenceableCallsChanged() { -        for (Callback callback : mCallbacks) { -            callback.onConferenceableCallsChanged(this, mUnmodifiableConferenceableCalls); +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final Call call = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls); +                } +            });          }      }  } diff --git a/telecomm/java/android/telecom/CallbackRecord.java b/telecomm/java/android/telecom/CallbackRecord.java new file mode 100644 index 000000000000..1a81925dd248 --- /dev/null +++ b/telecomm/java/android/telecom/CallbackRecord.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 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 android.telecom; + +import android.os.Handler; + + +/** + * This class is used to associate a generic callback of type T with a handler to which commands and + * status updates will be delivered to. + * + * @hide + */ +class CallbackRecord<T> { +    private final T mCallback; +    private final Handler mHandler; + +    public CallbackRecord(T callback, Handler handler) { +        mCallback = callback; +        mHandler = handler; +    } + +    public T getCallback() { +        return mCallback; +    } + +    public Handler getHandler() { +        return mHandler; +    } +} diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java index 2c8415ada5a6..3cb4e871600e 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -362,6 +362,9 @@ public abstract class InCallService extends Service {       */      public static abstract class VideoCall { +        /** @hide */ +        public abstract void destroy(); +          /**           * Registers a callback to receive commands and state changes for video calls.           * @@ -370,9 +373,17 @@ public abstract class InCallService extends Service {          public abstract void registerCallback(VideoCall.Callback callback);          /** +         * Registers a callback to receive commands and state changes for video calls. +         * +         * @param callback The video call callback. +         * @param handler A handler which commands and status changes will be delivered to. +         */ +        public abstract void registerCallback(VideoCall.Callback callback, Handler handler); + +        /**           * Clears the video call listener set via {@link #registerCallback}.           */ -        public abstract void unregisterCallback(); +        public abstract void unregisterCallback(VideoCall.Callback callback);          /**           * Sets the camera to be used for video recording in a video call. diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java index 3d9acda688c8..4cdfd2eb8f56 100644 --- a/telecomm/java/android/telecom/Phone.java +++ b/telecomm/java/android/telecom/Phone.java @@ -125,7 +125,7 @@ public final class Phone {          InCallService.VideoCall videoCall = call.getVideoCall();          if (videoCall != null) { -            videoCall.unregisterCallback(); +            videoCall.destroy();          }          fireCallRemoved(call);      } @@ -174,7 +174,7 @@ public final class Phone {          for (Call call : mCalls) {              InCallService.VideoCall videoCall = call.getVideoCall();              if (videoCall != null) { -                videoCall.unregisterCallback(); +                videoCall.destroy();              }              if (call.getState() != Call.STATE_DISCONNECTED) {                  call.internalSetDisconnected(); diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java index fba3ee3265f9..a76bf5998a51 100644 --- a/telecomm/java/android/telecom/RemoteConference.java +++ b/telecomm/java/android/telecom/RemoteConference.java @@ -18,6 +18,7 @@ package android.telecom;  import com.android.internal.telecom.IConnectionService; +import android.os.Handler;  import android.os.RemoteException;  import java.util.ArrayList; @@ -49,7 +50,7 @@ public final class RemoteConference {      private final String mId;      private final IConnectionService mConnectionService; -    private final Set<Callback> mCallbacks = new CopyOnWriteArraySet<>(); +    private final Set<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArraySet<>();      private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();      private final List<RemoteConnection> mUnmodifiableChildConnections =              Collections.unmodifiableList(mChildConnections); @@ -77,13 +78,20 @@ public final class RemoteConference {          for (RemoteConnection connection : mChildConnections) {              connection.setConference(null);          } -        for (Callback c : mCallbacks) { -            c.onDestroyed(this); +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final RemoteConference conference = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onDestroyed(conference); +                } +            });          }      }      /** {@hide} */ -    void setState(int newState) { +    void setState(final int newState) {          if (newState != Connection.STATE_ACTIVE &&                  newState != Connection.STATE_HOLDING &&                  newState != Connection.STATE_DISCONNECTED) { @@ -93,42 +101,71 @@ public final class RemoteConference {          }          if (mState != newState) { -            int oldState = mState; +            final int oldState = mState;              mState = newState; -            for (Callback c : mCallbacks) { -                c.onStateChanged(this, oldState, newState); +            for (CallbackRecord<Callback> record : mCallbackRecords) { +                final RemoteConference conference = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onStateChanged(conference, oldState, newState); +                    } +                });              }          }      }      /** {@hide} */ -    void addConnection(RemoteConnection connection) { +    void addConnection(final RemoteConnection connection) {          if (!mChildConnections.contains(connection)) {              mChildConnections.add(connection);              connection.setConference(this); -            for (Callback c : mCallbacks) { -                c.onConnectionAdded(this, connection); +            for (CallbackRecord<Callback> record : mCallbackRecords) { +                final RemoteConference conference = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onConnectionAdded(conference, connection); +                    } +                });              }          }      }      /** {@hide} */ -    void removeConnection(RemoteConnection connection) { +    void removeConnection(final RemoteConnection connection) {          if (mChildConnections.contains(connection)) {              mChildConnections.remove(connection);              connection.setConference(null); -            for (Callback c : mCallbacks) { -                c.onConnectionRemoved(this, connection); +            for (CallbackRecord<Callback> record : mCallbackRecords) { +                final RemoteConference conference = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onConnectionRemoved(conference, connection); +                    } +                });              }          }      }      /** {@hide} */ -    void setConnectionCapabilities(int connectionCapabilities) { +    void setConnectionCapabilities(final int connectionCapabilities) {          if (mConnectionCapabilities != connectionCapabilities) {              mConnectionCapabilities = connectionCapabilities; -            for (Callback c : mCallbacks) { -                c.onConnectionCapabilitiesChanged(this, mConnectionCapabilities); +            for (CallbackRecord<Callback> record : mCallbackRecords) { +                final RemoteConference conference = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onConnectionCapabilitiesChanged( +                                conference, mConnectionCapabilities); +                    } +                });              }          }      } @@ -137,18 +174,33 @@ public final class RemoteConference {      void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) {          mConferenceableConnections.clear();          mConferenceableConnections.addAll(conferenceableConnections); -        for (Callback c : mCallbacks) { -            c.onConferenceableConnectionsChanged(this, mUnmodifiableConferenceableConnections); +        for (CallbackRecord<Callback> record : mCallbackRecords) { +            final RemoteConference conference = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onConferenceableConnectionsChanged( +                            conference, mUnmodifiableConferenceableConnections); +                } +            });          }      }      /** {@hide} */ -    void setDisconnected(DisconnectCause disconnectCause) { +    void setDisconnected(final DisconnectCause disconnectCause) {          if (mState != Connection.STATE_DISCONNECTED) {              mDisconnectCause = disconnectCause;              setState(Connection.STATE_DISCONNECTED); -            for (Callback c : mCallbacks) { -                c.onDisconnected(this, disconnectCause); +            for (CallbackRecord<Callback> record : mCallbackRecords) { +                final RemoteConference conference = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onDisconnected(conference, disconnectCause); +                    } +                });              }          }      } @@ -239,10 +291,24 @@ public final class RemoteConference {      }      public final void registerCallback(Callback callback) { -        mCallbacks.add(callback); +        registerCallback(callback, new Handler()); +    } + +    public final void registerCallback(Callback callback, Handler handler) { +        unregisterCallback(callback); +        if (callback != null && handler != null) { +            mCallbackRecords.add(new CallbackRecord(callback, handler)); +        }      }      public final void unregisterCallback(Callback callback) { -        mCallbacks.remove(callback); +        if (callback != null) { +            for (CallbackRecord<Callback> record : mCallbackRecords) { +                if (record.getCallback() == callback) { +                    mCallbackRecords.remove(record); +                    break; +                } +            } +        }      }  } diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 4ecfd50e705a..1493b208ad69 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -21,6 +21,7 @@ import com.android.internal.telecom.IVideoCallback;  import com.android.internal.telecom.IVideoProvider;  import android.net.Uri; +import android.os.Handler;  import android.os.IBinder;  import android.os.RemoteException;  import android.view.Surface; @@ -392,8 +393,8 @@ public final class RemoteConnection {       * load factor before resizing, 1 means we only expect a single thread to       * access the map so make only a single shard       */ -    private final Set<Callback> mCallbacks = Collections.newSetFromMap( -            new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1)); +    private final Set<CallbackRecord> mCallbackRecords = Collections.newSetFromMap( +            new ConcurrentHashMap<CallbackRecord, Boolean>(8, 0.9f, 1));      private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>();      private final List<RemoteConnection> mUnmodifiableconferenceableConnections =              Collections.unmodifiableList(mConferenceableConnections); @@ -470,7 +471,20 @@ public final class RemoteConnection {       * @param callback A {@code Callback}.       */      public void registerCallback(Callback callback) { -        mCallbacks.add(callback); +        registerCallback(callback, new Handler()); +    } + +    /** +     * Adds a callback to this {@code RemoteConnection}. +     * +     * @param callback A {@code Callback}. +     * @param handler A {@code Handler} which command and status changes will be delivered to. +     */ +    public void registerCallback(Callback callback, Handler handler) { +        unregisterCallback(callback); +        if (callback != null && handler != null) { +            mCallbackRecords.add(new CallbackRecord(callback, handler)); +        }      }      /** @@ -480,7 +494,12 @@ public final class RemoteConnection {       */      public void unregisterCallback(Callback callback) {          if (callback != null) { -            mCallbacks.remove(callback); +            for (CallbackRecord record : mCallbackRecords) { +                if (record.getCallback() == callback) { +                    mCallbackRecords.remove(record); +                    break; +                } +            }          }      } @@ -800,11 +819,18 @@ public final class RemoteConnection {      /**       * @hide       */ -    void setState(int state) { +    void setState(final int state) {          if (mState != state) {              mState = state; -            for (Callback c: mCallbacks) { -                c.onStateChanged(this, state); +            for (CallbackRecord record: mCallbackRecords) { +                final RemoteConnection connection = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onStateChanged(connection, state); +                    } +                });              }          }      } @@ -812,13 +838,20 @@ public final class RemoteConnection {      /**       * @hide       */ -    void setDisconnected(DisconnectCause disconnectCause) { +    void setDisconnected(final DisconnectCause disconnectCause) {          if (mState != Connection.STATE_DISCONNECTED) {              mState = Connection.STATE_DISCONNECTED;              mDisconnectCause = disconnectCause; -            for (Callback c : mCallbacks) { -                c.onDisconnected(this, mDisconnectCause); +            for (CallbackRecord record : mCallbackRecords) { +                final RemoteConnection connection = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onDisconnected(connection, disconnectCause); +                    } +                });              }          }      } @@ -826,11 +859,18 @@ public final class RemoteConnection {      /**       * @hide       */ -    void setRingbackRequested(boolean ringback) { +    void setRingbackRequested(final boolean ringback) {          if (mRingbackRequested != ringback) {              mRingbackRequested = ringback; -            for (Callback c : mCallbacks) { -                c.onRingbackRequested(this, ringback); +            for (CallbackRecord record : mCallbackRecords) { +                final RemoteConnection connection = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onRingbackRequested(connection, ringback); +                    } +                });              }          }      } @@ -838,10 +878,17 @@ public final class RemoteConnection {      /**       * @hide       */ -    void setConnectionCapabilities(int connectionCapabilities) { +    void setConnectionCapabilities(final int connectionCapabilities) {          mConnectionCapabilities = connectionCapabilities; -        for (Callback c : mCallbacks) { -            c.onConnectionCapabilitiesChanged(this, connectionCapabilities); +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onConnectionCapabilitiesChanged(connection, connectionCapabilities); +                } +            });          }      } @@ -849,17 +896,24 @@ public final class RemoteConnection {       * @hide       */      void setDestroyed() { -        if (!mCallbacks.isEmpty()) { +        if (!mCallbackRecords.isEmpty()) {              // Make sure that the callbacks are notified that the call is destroyed first.              if (mState != Connection.STATE_DISCONNECTED) {                  setDisconnected(                          new DisconnectCause(DisconnectCause.ERROR, "Connection destroyed."));              } -            for (Callback c : mCallbacks) { -                c.onDestroyed(this); +            for (CallbackRecord record : mCallbackRecords) { +                final RemoteConnection connection = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onDestroyed(connection); +                    } +                });              } -            mCallbacks.clear(); +            mCallbackRecords.clear();              mConnected = false;          } @@ -868,90 +922,162 @@ public final class RemoteConnection {      /**       * @hide       */ -    void setPostDialWait(String remainingDigits) { -        for (Callback c : mCallbacks) { -            c.onPostDialWait(this, remainingDigits); +    void setPostDialWait(final String remainingDigits) { +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onPostDialWait(connection, remainingDigits); +                } +            });          }      }      /**       * @hide       */ -    void onPostDialChar(char nextChar) { -        for (Callback c : mCallbacks) { -            c.onPostDialChar(this, nextChar); +    void onPostDialChar(final char nextChar) { +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onPostDialWait(connection, String.valueOf(nextChar)); +                } +            });          }      }      /**       * @hide       */ -    void setVideoState(int videoState) { +    void setVideoState(final int videoState) {          mVideoState = videoState; -        for (Callback c : mCallbacks) { -            c.onVideoStateChanged(this, videoState); +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onVideoStateChanged(connection, videoState); +                } +            });          }      }      /**       * @hide       */ -    void setVideoProvider(VideoProvider videoProvider) { +    void setVideoProvider(final VideoProvider videoProvider) {          mVideoProvider = videoProvider; -        for (Callback c : mCallbacks) { -            c.onVideoProviderChanged(this, videoProvider); +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onVideoProviderChanged(connection, videoProvider); +                } +            });          }      }      /** @hide */ -    void setIsVoipAudioMode(boolean isVoip) { +    void setIsVoipAudioMode(final boolean isVoip) {          mIsVoipAudioMode = isVoip; -        for (Callback c : mCallbacks) { -            c.onVoipAudioChanged(this, isVoip); +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onVoipAudioChanged(connection, isVoip); +                } +            });          }      }      /** @hide */ -    void setStatusHints(StatusHints statusHints) { +    void setStatusHints(final StatusHints statusHints) {          mStatusHints = statusHints; -        for (Callback c : mCallbacks) { -            c.onStatusHintsChanged(this, statusHints); +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onStatusHintsChanged(connection, statusHints); +                } +            });          }      }      /** @hide */ -    void setAddress(Uri address, int presentation) { +    void setAddress(final Uri address, final int presentation) {          mAddress = address;          mAddressPresentation = presentation; -        for (Callback c : mCallbacks) { -            c.onAddressChanged(this, address, presentation); +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onAddressChanged(connection, address, presentation); +                } +            });          }      }      /** @hide */ -    void setCallerDisplayName(String callerDisplayName, int presentation) { +    void setCallerDisplayName(final String callerDisplayName, final int presentation) {          mCallerDisplayName = callerDisplayName;          mCallerDisplayNamePresentation = presentation; -        for (Callback c : mCallbacks) { -            c.onCallerDisplayNameChanged(this, callerDisplayName, presentation); +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onCallerDisplayNameChanged( +                            connection, callerDisplayName, presentation); +                } +            });          }      }      /** @hide */ -    void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) { +    void setConferenceableConnections(final List<RemoteConnection> conferenceableConnections) {          mConferenceableConnections.clear();          mConferenceableConnections.addAll(conferenceableConnections); -        for (Callback c : mCallbacks) { -            c.onConferenceableConnectionsChanged(this, mUnmodifiableconferenceableConnections); +        for (CallbackRecord record : mCallbackRecords) { +            final RemoteConnection connection = this; +            final Callback callback = record.getCallback(); +            record.getHandler().post(new Runnable() { +                @Override +                public void run() { +                    callback.onConferenceableConnectionsChanged( +                            connection, mUnmodifiableconferenceableConnections); +                } +            });          }      }      /** @hide */ -    void setConference(RemoteConference conference) { +    void setConference(final RemoteConference conference) {          if (mConference != conference) {              mConference = conference; -            for (Callback c : mCallbacks) { -                c.onConferenceChanged(this, conference); +            for (CallbackRecord record : mCallbackRecords) { +                final RemoteConnection connection = this; +                final Callback callback = record.getCallback(); +                record.getHandler().post(new Runnable() { +                    @Override +                    public void run() { +                        callback.onConferenceChanged(connection, conference); +                    } +                });              }          }      } @@ -968,4 +1094,22 @@ public final class RemoteConnection {      public static RemoteConnection failure(DisconnectCause disconnectCause) {          return new RemoteConnection(disconnectCause);      } + +    private static final class CallbackRecord extends Callback { +        private final Callback mCallback; +        private final Handler mHandler; + +        public CallbackRecord(Callback callback, Handler handler) { +            mCallback = callback; +            mHandler = handler; +        } + +        public Callback getCallback() { +            return mCallback; +        } + +        public Handler getHandler() { +            return mHandler; +        } +    }  } diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java index 3779d1aeca01..7a82c1bb3e3d 100644 --- a/telecomm/java/android/telecom/VideoCallImpl.java +++ b/telecomm/java/android/telecom/VideoCallImpl.java @@ -36,13 +36,6 @@ import com.android.internal.telecom.IVideoProvider;   * {@hide}   */  public class VideoCallImpl extends VideoCall { -    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 static final int MSG_CHANGE_VIDEO_QUALITY = 7;      private final IVideoProvider mVideoProvider;      private final VideoCallListenerBinder mBinder; @@ -61,7 +54,7 @@ public class VideoCallImpl extends VideoCall {      private final class VideoCallListenerBinder extends IVideoCallback.Stub {          @Override          public void receiveSessionModifyRequest(VideoProfile videoProfile) { -            mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_REQUEST, +            mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,                      videoProfile).sendToTarget();          } @@ -72,12 +65,14 @@ public class VideoCallImpl extends VideoCall {              args.arg1 = status;              args.arg2 = requestProfile;              args.arg3 = responseProfile; -            mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args).sendToTarget(); +            mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args) +                    .sendToTarget();          }          @Override          public void handleCallSessionEvent(int event) { -            mHandler.obtainMessage(MSG_HANDLE_CALL_SESSION_EVENT, event).sendToTarget(); +            mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event) +                    .sendToTarget();          }          @Override @@ -85,28 +80,42 @@ public class VideoCallImpl extends VideoCall {              SomeArgs args = SomeArgs.obtain();              args.arg1 = width;              args.arg2 = height; -            mHandler.obtainMessage(MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget(); +            mHandler.obtainMessage(MessageHandler.MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();          }          @Override          public void changeVideoQuality(int videoQuality) { -            mHandler.obtainMessage(MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0).sendToTarget(); +            mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0) +                    .sendToTarget();          }          @Override          public void changeCallDataUsage(long dataUsage) { -            mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, dataUsage).sendToTarget(); +            mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage) +                    .sendToTarget();          }          @Override          public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) { -            mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES, +            mHandler.obtainMessage(MessageHandler.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()) { +    private final class MessageHandler extends Handler { +        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 static final int MSG_CHANGE_VIDEO_QUALITY = 7; + +        public MessageHandler(Looper looper) { +            super(looper); +        } +          @Override          public void handleMessage(Message msg) {              if (mCallback == null) { @@ -160,7 +169,8 @@ public class VideoCallImpl extends VideoCall {          }      }; -    /** {@hide} */ +    private Handler mHandler; +      VideoCallImpl(IVideoProvider videoProvider) throws RemoteException {          mVideoProvider = videoProvider;          mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0); @@ -169,13 +179,31 @@ public class VideoCallImpl extends VideoCall {          mVideoProvider.addVideoCallback(mBinder);      } +    public void destroy() { +        unregisterCallback(mCallback); +    } +      /** {@inheritDoc} */      public void registerCallback(VideoCall.Callback callback) { +        registerCallback(callback, null); +    } + +    /** {@inheritDoc} */ +    public void registerCallback(VideoCall.Callback callback, Handler handler) {          mCallback = callback; +        if (handler == null) { +            mHandler = new MessageHandler(Looper.getMainLooper()); +        } else { +            mHandler = new MessageHandler(handler.getLooper()); +        }      }      /** {@inheritDoc} */ -    public void unregisterCallback() { +    public void unregisterCallback(VideoCall.Callback callback) { +        if (callback != mCallback) { +            return; +        } +          mCallback = null;          try {              mVideoProvider.removeVideoCallback(mBinder);  |