ImsServiceProxy.java revision e63b35d0b22db8769ffd3378fc305d5f3d27fd50
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 callServiceType, int callType) 139 throws RemoteException { 140 synchronized (mLock) { 141 checkBinderConnection(); 142 return getServiceInterface(mBinder).isConnected(mSlotId, mSupportedFeature, 143 callServiceType, callType); 144 } 145 } 146 147 @Override 148 public boolean isOpened() throws RemoteException { 149 synchronized (mLock) { 150 checkBinderConnection(); 151 return getServiceInterface(mBinder).isOpened(mSlotId, mSupportedFeature); 152 } 153 } 154 155 @Override 156 public void addRegistrationListener(IImsRegistrationListener listener) 157 throws RemoteException { 158 synchronized (mLock) { 159 checkBinderConnection(); 160 getServiceInterface(mBinder).addRegistrationListener(mSlotId, mSupportedFeature, 161 listener); 162 } 163 } 164 165 @Override 166 public void removeRegistrationListener(IImsRegistrationListener listener) 167 throws RemoteException { 168 synchronized (mLock) { 169 checkBinderConnection(); 170 getServiceInterface(mBinder).removeRegistrationListener(mSlotId, mSupportedFeature, 171 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() throws RemoteException { 207 synchronized (mLock) { 208 checkBinderConnection(); 209 return getServiceInterface(mBinder).getUtInterface(mSlotId, mSupportedFeature); 210 } 211 } 212 213 @Override 214 public IImsConfig getConfigInterface() throws RemoteException { 215 synchronized (mLock) { 216 checkBinderConnection(); 217 return getServiceInterface(mBinder).getConfigInterface(mSlotId, mSupportedFeature); 218 } 219 } 220 221 @Override 222 public void turnOnIms() throws RemoteException { 223 synchronized (mLock) { 224 checkBinderConnection(); 225 getServiceInterface(mBinder).turnOnIms(mSlotId, mSupportedFeature); 226 } 227 } 228 229 @Override 230 public void turnOffIms() throws RemoteException { 231 synchronized (mLock) { 232 checkBinderConnection(); 233 getServiceInterface(mBinder).turnOffIms(mSlotId, mSupportedFeature); 234 } 235 } 236 237 @Override 238 public IImsEcbm getEcbmInterface() throws RemoteException { 239 synchronized (mLock) { 240 checkBinderConnection(); 241 return getServiceInterface(mBinder).getEcbmInterface(mSlotId, mSupportedFeature); 242 } 243 } 244 245 @Override 246 public void setUiTTYMode(int uiTtyMode, Message onComplete) 247 throws RemoteException { 248 synchronized (mLock) { 249 checkBinderConnection(); 250 getServiceInterface(mBinder).setUiTTYMode(mSlotId, mSupportedFeature, uiTtyMode, 251 onComplete); 252 } 253 } 254 255 @Override 256 public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException { 257 synchronized (mLock) { 258 checkBinderConnection(); 259 return getServiceInterface(mBinder).getMultiEndpointInterface(mSlotId, 260 mSupportedFeature); 261 } 262 } 263 264 @Override 265 public int getFeatureStatus() { 266 synchronized (mLock) { 267 if (mFeatureStatusCached != null) { 268 return mFeatureStatusCached; 269 } 270 } 271 // Don't synchronize on Binder call. 272 Integer status = retrieveFeatureStatus(); 273 synchronized (mLock) { 274 if (status == null) { 275 return ImsFeature.STATE_NOT_AVAILABLE; 276 } 277 // Cache only non-null value for feature status. 278 mFeatureStatusCached = status; 279 } 280 return status; 281 } 282 283 /** 284 * Internal method used to retrieve the feature status from the corresponding ImsService. 285 */ 286 private Integer retrieveFeatureStatus() { 287 if (mBinder != null) { 288 try { 289 return getServiceInterface(mBinder).getFeatureStatus(mSlotId, mSupportedFeature); 290 } catch (RemoteException e) { 291 // Status check failed, don't update cache 292 } 293 } 294 return null; 295 } 296 297 /** 298 * @param c Callback that will fire when the feature status has changed. 299 */ 300 public void setStatusCallback(INotifyStatusChanged c) { 301 mStatusCallback = c; 302 } 303 304 @Override 305 public boolean isBinderAlive() { 306 return mIsAvailable && getFeatureStatus() == ImsFeature.STATE_READY && mBinder != null && 307 mBinder.isBinderAlive(); 308 } 309 310 private IImsServiceController getServiceInterface(IBinder b) { 311 return IImsServiceController.Stub.asInterface(b); 312 } 313} 314