1 /* 2 * Copyright (C) 2019 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 17 package com.android.ims; 18 19 import android.content.Context; 20 import android.net.Uri; 21 import android.os.IBinder; 22 import android.os.RemoteException; 23 import android.telephony.ims.aidl.ICapabilityExchangeEventListener; 24 import android.telephony.ims.aidl.IImsCapabilityCallback; 25 import android.telephony.ims.aidl.IImsConfig; 26 import android.telephony.ims.aidl.IImsRcsFeature; 27 import android.telephony.ims.aidl.IImsRegistration; 28 import android.telephony.ims.aidl.IImsRegistrationCallback; 29 import android.telephony.ims.aidl.IPublishResponseCallback; 30 import android.telephony.ims.aidl.IOptionsResponseCallback; 31 import android.telephony.ims.aidl.ISipTransport; 32 import android.telephony.ims.aidl.ISubscribeResponseCallback; 33 import android.telephony.ims.feature.CapabilityChangeRequest; 34 35 import com.android.internal.annotations.VisibleForTesting; 36 import com.android.telephony.Rlog; 37 38 import java.util.List; 39 40 /** 41 * A container of the IImsServiceController binder, which implements all of the RcsFeatures that 42 * the platform currently supports: RCS 43 */ 44 public class RcsFeatureConnection extends FeatureConnection { 45 private static final String TAG = "RcsFeatureConnection"; 46 47 public class AvailabilityCallbackManager extends 48 ImsCallbackAdapterManager<IImsCapabilityCallback> { 49 AvailabilityCallbackManager(Context context)50 AvailabilityCallbackManager(Context context) { 51 super(context, new Object() /* Lock object */, mSlotId, mSubId); 52 } 53 54 @Override registerCallback(IImsCapabilityCallback localCallback)55 public void registerCallback(IImsCapabilityCallback localCallback) { 56 try { 57 addCapabilityCallback(localCallback); 58 } catch (RemoteException e) { 59 loge("Register capability callback error: " + e); 60 throw new IllegalStateException( 61 " CapabilityCallbackManager: Register callback error"); 62 } 63 } 64 65 @Override unregisterCallback(IImsCapabilityCallback localCallback)66 public void unregisterCallback(IImsCapabilityCallback localCallback) { 67 try { 68 removeCapabilityCallback(localCallback); 69 } catch (RemoteException e) { 70 loge("Cannot remove capability callback: " + e); 71 } 72 } 73 } 74 75 private class RegistrationCallbackManager extends 76 ImsCallbackAdapterManager<IImsRegistrationCallback> { 77 RegistrationCallbackManager(Context context)78 public RegistrationCallbackManager(Context context) { 79 super(context, new Object() /* Lock object */, mSlotId, mSubId); 80 } 81 82 @Override registerCallback(IImsRegistrationCallback localCallback)83 public void registerCallback(IImsRegistrationCallback localCallback) { 84 IImsRegistration imsRegistration = getRegistration(); 85 if (imsRegistration == null) { 86 loge("Register IMS registration callback: ImsRegistration is null"); 87 throw new IllegalStateException("RegistrationCallbackAdapter: RcsFeature is" 88 + " not available!"); 89 } 90 91 try { 92 imsRegistration.addRegistrationCallback(localCallback); 93 } catch (RemoteException e) { 94 throw new IllegalStateException("RegistrationCallbackAdapter: RcsFeature" 95 + " binder is dead."); 96 } 97 } 98 99 @Override unregisterCallback(IImsRegistrationCallback localCallback)100 public void unregisterCallback(IImsRegistrationCallback localCallback) { 101 IImsRegistration imsRegistration = getRegistration(); 102 if (imsRegistration == null) { 103 logi("Unregister IMS registration callback: ImsRegistration is null"); 104 return; 105 } 106 107 try { 108 imsRegistration.removeRegistrationCallback(localCallback); 109 } catch (RemoteException e) { 110 loge("Cannot remove registration callback: " + e); 111 } 112 } 113 } 114 115 private final AvailabilityCallbackManager mAvailabilityCallbackManager; 116 private final RegistrationCallbackManager mRegistrationCallbackManager; 117 RcsFeatureConnection(Context context, int slotId, int subId, IImsRcsFeature feature, IImsConfig c, IImsRegistration r, ISipTransport s)118 public RcsFeatureConnection(Context context, int slotId, int subId, IImsRcsFeature feature, 119 IImsConfig c, IImsRegistration r, ISipTransport s) { 120 super(context, slotId, subId, c, r, s); 121 mAvailabilityCallbackManager = new AvailabilityCallbackManager(mContext); 122 mRegistrationCallbackManager = new RegistrationCallbackManager(mContext); 123 setBinder(feature != null ? feature.asBinder() : null); 124 } 125 close()126 public void close() { 127 removeCapabilityExchangeEventListener(); 128 mAvailabilityCallbackManager.close(); 129 mRegistrationCallbackManager.close(); 130 } 131 132 @Override onRemovedOrDied()133 protected void onRemovedOrDied() { 134 close(); 135 super.onRemovedOrDied(); 136 } 137 setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener)138 public void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener) 139 throws RemoteException { 140 synchronized (mLock) { 141 // Only check if service is alive. The feature status may not be READY. 142 checkServiceIsAlive(); 143 getServiceInterface(mBinder).setCapabilityExchangeEventListener(listener); 144 } 145 } 146 removeCapabilityExchangeEventListener()147 public void removeCapabilityExchangeEventListener() { 148 try { 149 setCapabilityExchangeEventListener(null); 150 } catch (RemoteException e) { 151 // If we are not still connected, there is no need to fail removing. 152 } 153 } 154 checkServiceIsAlive()155 private void checkServiceIsAlive() throws RemoteException { 156 if (!sImsSupportedOnDevice) { 157 throw new RemoteException("IMS is not supported on this device."); 158 } 159 if (!isBinderAlive()) { 160 throw new RemoteException("ImsServiceProxy is not alive."); 161 } 162 } 163 queryCapabilityStatus()164 public int queryCapabilityStatus() throws RemoteException { 165 synchronized (mLock) { 166 checkServiceIsReady(); 167 return getServiceInterface(mBinder).queryCapabilityStatus(); 168 } 169 } 170 addCallbackForSubscription(int subId, IImsCapabilityCallback cb)171 public void addCallbackForSubscription(int subId, IImsCapabilityCallback cb) { 172 mAvailabilityCallbackManager.addCallbackForSubscription(cb, subId); 173 } 174 addCallbackForSubscription(int subId, IImsRegistrationCallback cb)175 public void addCallbackForSubscription(int subId, IImsRegistrationCallback cb) { 176 mRegistrationCallbackManager.addCallbackForSubscription(cb, subId); 177 } 178 addCallback(IImsRegistrationCallback cb)179 public void addCallback(IImsRegistrationCallback cb) { 180 mRegistrationCallbackManager.addCallback(cb); 181 } 182 removeCallbackForSubscription(int subId, IImsCapabilityCallback cb)183 public void removeCallbackForSubscription(int subId, IImsCapabilityCallback cb) { 184 mAvailabilityCallbackManager.removeCallback(cb); 185 } 186 removeCallbackForSubscription(int subId, IImsRegistrationCallback cb)187 public void removeCallbackForSubscription(int subId, IImsRegistrationCallback cb) { 188 mRegistrationCallbackManager.removeCallback(cb); 189 } 190 removeCallback(IImsRegistrationCallback cb)191 public void removeCallback(IImsRegistrationCallback cb) { 192 mRegistrationCallbackManager.removeCallback(cb); 193 } 194 195 // Add callback to remote service addCapabilityCallback(IImsCapabilityCallback callback)196 private void addCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException { 197 synchronized (mLock) { 198 checkServiceIsReady(); 199 getServiceInterface(mBinder).addCapabilityCallback(callback); 200 } 201 } 202 203 // Remove callback to remote service removeCapabilityCallback(IImsCapabilityCallback callback)204 private void removeCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException { 205 synchronized (mLock) { 206 checkServiceIsReady(); 207 getServiceInterface(mBinder).removeCapabilityCallback(callback); 208 } 209 } 210 queryCapabilityConfiguration(int capability, int radioTech, IImsCapabilityCallback c)211 public void queryCapabilityConfiguration(int capability, int radioTech, 212 IImsCapabilityCallback c) throws RemoteException { 213 synchronized (mLock) { 214 checkServiceIsReady(); 215 getServiceInterface(mBinder).queryCapabilityConfiguration(capability, radioTech, c); 216 } 217 } 218 changeEnabledCapabilities(CapabilityChangeRequest request, IImsCapabilityCallback callback)219 public void changeEnabledCapabilities(CapabilityChangeRequest request, 220 IImsCapabilityCallback callback) throws RemoteException { 221 synchronized (mLock) { 222 checkServiceIsReady(); 223 getServiceInterface(mBinder).changeCapabilitiesConfiguration(request, callback); 224 } 225 } 226 requestPublication(String pidfXml, IPublishResponseCallback responseCallback)227 public void requestPublication(String pidfXml, IPublishResponseCallback responseCallback) 228 throws RemoteException { 229 synchronized (mLock) { 230 checkServiceIsReady(); 231 getServiceInterface(mBinder).publishCapabilities(pidfXml, responseCallback); 232 } 233 } 234 requestCapabilities(List<Uri> uris, ISubscribeResponseCallback c)235 public void requestCapabilities(List<Uri> uris, ISubscribeResponseCallback c) 236 throws RemoteException { 237 synchronized (mLock) { 238 checkServiceIsReady(); 239 getServiceInterface(mBinder).subscribeForCapabilities(uris, c); 240 } 241 } 242 sendOptionsCapabilityRequest(Uri contactUri, List<String> myCapabilities, IOptionsResponseCallback callback)243 public void sendOptionsCapabilityRequest(Uri contactUri, List<String> myCapabilities, 244 IOptionsResponseCallback callback) throws RemoteException { 245 synchronized (mLock) { 246 checkServiceIsReady(); 247 getServiceInterface(mBinder).sendOptionsCapabilityRequest(contactUri, myCapabilities, 248 callback); 249 } 250 } 251 252 @Override 253 @VisibleForTesting retrieveFeatureState()254 public Integer retrieveFeatureState() { 255 if (mBinder != null) { 256 try { 257 return getServiceInterface(mBinder).getFeatureState(); 258 } catch (RemoteException e) { 259 // Status check failed, don't update cache 260 } 261 } 262 return null; 263 } 264 265 @Override onFeatureCapabilitiesUpdated(long capabilities)266 public void onFeatureCapabilitiesUpdated(long capabilities) 267 { 268 // doesn't do anything for RCS yet. 269 } 270 271 @VisibleForTesting getServiceInterface(IBinder b)272 public IImsRcsFeature getServiceInterface(IBinder b) { 273 return IImsRcsFeature.Stub.asInterface(b); 274 } log(String s)275 private void log(String s) { 276 Rlog.d(TAG + " [" + mSlotId + "]", s); 277 } 278 logi(String s)279 private void logi(String s) { 280 Rlog.i(TAG + " [" + mSlotId + "]", s); 281 } 282 loge(String s)283 private void loge(String s) { 284 Rlog.e(TAG + " [" + mSlotId + "]", s); 285 } 286 } 287