ImsServiceProxy.java revision 1639c21be6e7cd7699db4080fcf2ccc5cb2006e6
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package android.telephony.ims;
18
19import android.app.PendingIntent;
20import android.os.IBinder;
21import android.os.Message;
22import android.os.RemoteException;
23import android.telephony.ims.feature.IRcsFeature;
24import android.telephony.ims.feature.ImsFeature;
25import android.util.Log;
26
27import com.android.ims.ImsCallProfile;
28import com.android.ims.internal.IImsCallSession;
29import com.android.ims.internal.IImsCallSessionListener;
30import com.android.ims.internal.IImsConfig;
31import com.android.ims.internal.IImsEcbm;
32import com.android.ims.internal.IImsMultiEndpoint;
33import com.android.ims.internal.IImsRegistrationListener;
34import com.android.ims.internal.IImsServiceController;
35import com.android.ims.internal.IImsServiceFeatureListener;
36import com.android.ims.internal.IImsUt;
37
38/**
39 * A container of the IImsServiceController binder, which implements all of the ImsFeatures that
40 * the platform currently supports: MMTel and RCS.
41 * @hide
42 */
43
44public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeature {
45
46    protected String LOG_TAG = "ImsServiceProxy";
47    private final int mSupportedFeature;
48
49    // Start by assuming the proxy is available for usage.
50    private boolean mIsAvailable = true;
51    // ImsFeature Status from the ImsService. Cached.
52    private Integer mFeatureStatusCached = null;
53    private ImsServiceProxy.INotifyStatusChanged mStatusCallback;
54    private final Object mLock = new Object();
55
56    public interface INotifyStatusChanged {
57        void notifyStatusChanged();
58    }
59
60    private final IImsServiceFeatureListener mListenerBinder =
61            new IImsServiceFeatureListener.Stub() {
62
63        @Override
64        public void imsFeatureCreated(int slotId, int feature) throws RemoteException {
65            // The feature has been re-enabled. This may happen when the service crashes.
66            synchronized (mLock) {
67                if (!mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) {
68                    Log.i(LOG_TAG, "Feature enabled on slotId: " + slotId + " for feature: " +
69                            feature);
70                    mIsAvailable = true;
71                }
72            }
73        }
74
75        @Override
76        public void imsFeatureRemoved(int slotId, int feature) throws RemoteException {
77            synchronized (mLock) {
78                if (mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) {
79                    Log.i(LOG_TAG, "Feature disabled on slotId: " + slotId + " for feature: " +
80                            feature);
81                    mIsAvailable = false;
82                }
83            }
84        }
85
86        @Override
87        public void imsStatusChanged(int slotId, int feature, int status) throws RemoteException {
88            synchronized (mLock) {
89                Log.i(LOG_TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature +
90                        " status: " + status);
91                if (mSlotId == slotId && feature == mSupportedFeature) {
92                    mFeatureStatusCached = status;
93                }
94            }
95            if (mStatusCallback != null) {
96                mStatusCallback.notifyStatusChanged();
97            }
98        }
99    };
100
101    public ImsServiceProxy(int slotId, IBinder binder, int featureType) {
102        super(slotId, binder);
103        mSupportedFeature = featureType;
104    }
105
106    public ImsServiceProxy(int slotId, int featureType) {
107        super(slotId, null /*IBinder*/);
108        mSupportedFeature = featureType;
109    }
110
111    public IImsServiceFeatureListener getListener() {
112        return mListenerBinder;
113    }
114
115    public void setBinder(IBinder binder) {
116        mBinder = binder;
117    }
118
119    @Override
120    public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener)
121            throws RemoteException {
122        synchronized (mLock) {
123            checkBinderConnection();
124            return getServiceInterface(mBinder).startSession(mSlotId, mSupportedFeature,
125                    incomingCallIntent, listener);
126        }
127    }
128
129    @Override
130    public void endSession(int sessionId) throws RemoteException {
131        synchronized (mLock) {
132            checkBinderConnection();
133            getServiceInterface(mBinder).endSession(mSlotId, mSupportedFeature, sessionId);
134        }
135    }
136
137    @Override
138    public boolean isConnected(int sessionId, int callServiceType, int callType)
139            throws RemoteException {
140        synchronized (mLock) {
141            checkBinderConnection();
142            return getServiceInterface(mBinder).isConnected(mSlotId, mSupportedFeature, sessionId,
143                    callServiceType, callType);
144        }
145    }
146
147    @Override
148    public boolean isOpened(int sessionId) throws RemoteException {
149        synchronized (mLock) {
150            checkBinderConnection();
151            return getServiceInterface(mBinder).isOpened(mSlotId, mSupportedFeature, sessionId);
152        }
153    }
154
155    @Override
156    public void addRegistrationListener(int sessionId, IImsRegistrationListener listener)
157    throws RemoteException {
158        synchronized (mLock) {
159            checkBinderConnection();
160            getServiceInterface(mBinder).addRegistrationListener(mSlotId, mSupportedFeature,
161                    sessionId, listener);
162        }
163    }
164
165    @Override
166    public void removeRegistrationListener(int sessionId, IImsRegistrationListener listener)
167            throws RemoteException {
168        synchronized (mLock) {
169            checkBinderConnection();
170            getServiceInterface(mBinder).removeRegistrationListener(mSlotId, mSupportedFeature,
171                    sessionId, listener);
172        }
173    }
174
175    @Override
176    public ImsCallProfile createCallProfile(int sessionId, int callServiceType, int callType)
177            throws RemoteException {
178        synchronized (mLock) {
179            checkBinderConnection();
180            return getServiceInterface(mBinder).createCallProfile(mSlotId, mSupportedFeature,
181                    sessionId, callServiceType, callType);
182        }
183    }
184
185    @Override
186    public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile,
187            IImsCallSessionListener listener) throws RemoteException {
188        synchronized (mLock) {
189            checkBinderConnection();
190            return getServiceInterface(mBinder).createCallSession(mSlotId, mSupportedFeature,
191                    sessionId, profile, listener);
192        }
193    }
194
195    @Override
196    public IImsCallSession getPendingCallSession(int sessionId, String callId)
197            throws RemoteException {
198        synchronized (mLock) {
199            checkBinderConnection();
200            return getServiceInterface(mBinder).getPendingCallSession(mSlotId, mSupportedFeature,
201                    sessionId, callId);
202        }
203    }
204
205    @Override
206    public IImsUt getUtInterface(int sessionId) throws RemoteException {
207        synchronized (mLock) {
208            checkBinderConnection();
209            return getServiceInterface(mBinder).getUtInterface(mSlotId, mSupportedFeature,
210                    sessionId);
211        }
212    }
213
214    @Override
215    public IImsConfig getConfigInterface(int sessionId) throws RemoteException {
216        synchronized (mLock) {
217            checkBinderConnection();
218            return getServiceInterface(mBinder).getConfigInterface(mSlotId, mSupportedFeature,
219                    sessionId);
220        }
221    }
222
223    @Override
224    public void turnOnIms(int sessionId) throws RemoteException {
225        synchronized (mLock) {
226            checkBinderConnection();
227            getServiceInterface(mBinder).turnOnIms(mSlotId, mSupportedFeature, sessionId);
228        }
229    }
230
231    @Override
232    public void turnOffIms(int sessionId) throws RemoteException {
233        synchronized (mLock) {
234            checkBinderConnection();
235            getServiceInterface(mBinder).turnOffIms(mSlotId, mSupportedFeature, sessionId);
236        }
237    }
238
239    @Override
240    public IImsEcbm getEcbmInterface(int sessionId) throws RemoteException {
241        synchronized (mLock) {
242            checkBinderConnection();
243            return getServiceInterface(mBinder).getEcbmInterface(mSlotId, mSupportedFeature,
244                    sessionId);
245        }
246    }
247
248    @Override
249    public void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete)
250            throws RemoteException {
251        synchronized (mLock) {
252            checkBinderConnection();
253            getServiceInterface(mBinder).setUiTTYMode(mSlotId, mSupportedFeature, sessionId,
254                    uiTtyMode, onComplete);
255        }
256    }
257
258    @Override
259    public IImsMultiEndpoint getMultiEndpointInterface(int sessionId) throws RemoteException {
260        synchronized (mLock) {
261            checkBinderConnection();
262            return getServiceInterface(mBinder).getMultiEndpointInterface(mSlotId,
263                    mSupportedFeature, sessionId);
264        }
265    }
266
267    @Override
268    public int getFeatureStatus() {
269        synchronized (mLock) {
270            if (mFeatureStatusCached != null) {
271                return mFeatureStatusCached;
272            }
273        }
274        // Don't synchronize on Binder call.
275        Integer status = retrieveFeatureStatus();
276        synchronized (mLock) {
277            if (status == null) {
278                return ImsFeature.STATE_NOT_AVAILABLE;
279            }
280            // Cache only non-null value for feature status.
281            mFeatureStatusCached = status;
282        }
283        return status;
284    }
285
286    /**
287     * Internal method used to retrieve the feature status from the corresponding ImsService.
288     */
289    private Integer retrieveFeatureStatus() {
290        if (mBinder != null) {
291            try {
292                return getServiceInterface(mBinder).getFeatureStatus(mSlotId, mSupportedFeature);
293            } catch (RemoteException e) {
294                // Status check failed, don't update cache
295            }
296        }
297        return null;
298    }
299
300    /**
301     * @param c Callback that will fire when the feature status has changed.
302     */
303    public void setStatusCallback(INotifyStatusChanged c) {
304        mStatusCallback = c;
305    }
306
307    @Override
308    public boolean isBinderAlive() {
309        return mIsAvailable && getFeatureStatus() == ImsFeature.STATE_READY && mBinder != null &&
310                mBinder.isBinderAlive();
311    }
312
313    private IImsServiceController getServiceInterface(IBinder b) {
314        return IImsServiceController.Stub.asInterface(b);
315    }
316}
317