1 /* 2 * Copyright (C) 2020 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.services.telephony.rcs; 18 19 import android.os.Binder; 20 import android.os.IBinder; 21 import android.os.RemoteException; 22 import android.telephony.ims.DelegateRegistrationState; 23 import android.telephony.ims.DelegateRequest; 24 import android.telephony.ims.FeatureTagState; 25 import android.telephony.ims.SipDelegateConfiguration; 26 import android.telephony.ims.SipDelegateImsConfiguration; 27 import android.telephony.ims.SipDelegateManager; 28 import android.telephony.ims.aidl.IImsRegistration; 29 import android.telephony.ims.aidl.ISipDelegate; 30 import android.telephony.ims.aidl.ISipDelegateMessageCallback; 31 import android.telephony.ims.aidl.ISipDelegateStateCallback; 32 import android.telephony.ims.aidl.ISipTransport; 33 import android.telephony.ims.stub.SipDelegate; 34 import android.util.LocalLog; 35 import android.util.Log; 36 37 import java.io.PrintWriter; 38 import java.util.Collections; 39 import java.util.List; 40 import java.util.NoSuchElementException; 41 import java.util.Set; 42 import java.util.concurrent.Executor; 43 import java.util.function.BiConsumer; 44 import java.util.function.Consumer; 45 46 /** 47 * Container for the active connection to the {@link SipDelegate} active on the ImsService. 48 * <p> 49 * New instances of this class will be created and destroyed new {@link SipDelegate}s are created 50 * and destroyed by the {@link SipDelegateController}. 51 */ 52 public class SipDelegateBinderConnection implements DelegateBinderStateManager, 53 IBinder.DeathRecipient { 54 private static final String LOG_TAG = "BinderConn"; 55 56 protected final int mSubId; 57 protected final Set<FeatureTagState> mDeniedTags; 58 protected final Executor mExecutor; 59 protected final List<StateCallback> mStateCallbacks; 60 61 private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE); 62 63 // Callback interface from ImsService to this Connection. State Events will be forwarded to IMS 64 // application through DelegateStateTracker. 65 private final ISipDelegateStateCallback mSipDelegateStateCallback = 66 new ISipDelegateStateCallback.Stub() { 67 @Override 68 public void onCreated(ISipDelegate delegate, 69 List<FeatureTagState> deniedFeatureTags) { 70 long token = Binder.clearCallingIdentity(); 71 try { 72 mExecutor.execute(() -> 73 notifySipDelegateCreated(delegate, deniedFeatureTags)); 74 } finally { 75 Binder.restoreCallingIdentity(token); 76 } 77 } 78 79 @Override 80 public void onFeatureTagRegistrationChanged( 81 DelegateRegistrationState registrationState) { 82 long token = Binder.clearCallingIdentity(); 83 try { 84 mExecutor.execute(() -> { 85 logi("onFeatureTagRegistrationChanged:" + registrationState); 86 for (StateCallback c : mStateCallbacks) { 87 c.onRegistrationStateChanged(registrationState); 88 } 89 }); 90 } finally { 91 Binder.restoreCallingIdentity(token); 92 } 93 } 94 95 @Override 96 public void onImsConfigurationChanged( 97 SipDelegateImsConfiguration registeredSipConfig) { 98 long token = Binder.clearCallingIdentity(); 99 try { 100 mExecutor.execute(() -> { 101 logi("onImsConfigurationChanged: version=" 102 + registeredSipConfig.getVersion()); 103 for (StateCallback c : mStateCallbacks) { 104 c.onImsConfigurationChanged(registeredSipConfig); 105 } 106 }); 107 } finally { 108 Binder.restoreCallingIdentity(token); 109 } 110 } 111 112 @Override 113 public void onConfigurationChanged( 114 SipDelegateConfiguration registeredSipConfig) { 115 long token = Binder.clearCallingIdentity(); 116 try { 117 mExecutor.execute(() -> { 118 logi("onConfigurationChanged"); 119 for (StateCallback c : mStateCallbacks) { 120 c.onConfigurationChanged(registeredSipConfig); 121 } 122 }); 123 } finally { 124 Binder.restoreCallingIdentity(token); 125 } 126 } 127 128 @Override 129 public void onDestroyed(int reason) { 130 long token = Binder.clearCallingIdentity(); 131 try { 132 mExecutor.execute(() -> notifySipDelegateDestroyed(reason)); 133 } finally { 134 Binder.restoreCallingIdentity(token); 135 } 136 } 137 }; 138 139 private final ISipTransport mSipTransport; 140 private final IImsRegistration mImsRegistration; 141 private final DelegateRequest mRequestedConfig; 142 143 private ISipDelegate mDelegateBinder; 144 private BiConsumer<ISipDelegate, Set<FeatureTagState>> mPendingCreatedConsumer; 145 private Consumer<Integer> mPendingDestroyedConsumer; 146 147 /** 148 * Create a new Connection object to manage the creation and destruction of a 149 * {@link SipDelegate}. 150 * @param subId The subid that this SipDelegate is being created for. 151 * @param sipTransport The SipTransport implementation that will be used to manage SipDelegates. 152 * @param registrationImpl The ImsRegistration implementation that will be used to manage 153 * registration changes in relation to the SipDelegates. 154 * @param requestedConfig The DelegateRequest to be sent to the ImsService. 155 * @param transportDeniedTags The feature tags that have already been denied by the 156 * SipTransportController and should not be requested. 157 * @param executor The Executor that all binder calls from the remote process will be executed 158 * on. 159 * @param stateCallbacks A list of callbacks that will each be called when the state of the 160 * SipDelegate changes. This will be called on the supplied executor. 161 */ SipDelegateBinderConnection(int subId, ISipTransport sipTransport, IImsRegistration registrationImpl, DelegateRequest requestedConfig, Set<FeatureTagState> transportDeniedTags, Executor executor, List<StateCallback> stateCallbacks)162 public SipDelegateBinderConnection(int subId, ISipTransport sipTransport, 163 IImsRegistration registrationImpl, DelegateRequest requestedConfig, 164 Set<FeatureTagState> transportDeniedTags, Executor executor, 165 List<StateCallback> stateCallbacks) { 166 mSubId = subId; 167 mSipTransport = sipTransport; 168 mImsRegistration = registrationImpl; 169 mRequestedConfig = requestedConfig; 170 mDeniedTags = transportDeniedTags; 171 mExecutor = executor; 172 mStateCallbacks = stateCallbacks; 173 } 174 175 @Override create(ISipDelegateMessageCallback cb, BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer)176 public boolean create(ISipDelegateMessageCallback cb, 177 BiConsumer<ISipDelegate, Set<FeatureTagState>> createdConsumer) { 178 try { 179 mSipTransport.createSipDelegate(mSubId, mRequestedConfig, mSipDelegateStateCallback, 180 cb); 181 mSipTransport.asBinder().linkToDeath(this, 0); 182 } catch (RemoteException e) { 183 logw("create called on unreachable SipTransport:" + e); 184 return false; 185 } 186 mPendingCreatedConsumer = createdConsumer; 187 return true; 188 } 189 190 @Override destroy(int reason, Consumer<Integer> destroyedConsumer)191 public void destroy(int reason, Consumer<Integer> destroyedConsumer) { 192 mPendingDestroyedConsumer = destroyedConsumer; 193 try { 194 if (mDelegateBinder != null) { 195 mSipTransport.destroySipDelegate(mDelegateBinder, reason); 196 } else { 197 mExecutor.execute(() -> notifySipDelegateDestroyed(reason)); 198 } 199 mStateCallbacks.clear(); 200 } catch (RemoteException e) { 201 logw("destroy called on unreachable SipTransport:" + e); 202 mExecutor.execute(() -> notifySipDelegateDestroyed(reason)); 203 } 204 try { 205 mSipTransport.asBinder().unlinkToDeath(this, 0); 206 } catch (NoSuchElementException e) { 207 logw("unlinkToDeath called on already unlinked binder" + e); 208 } 209 } 210 211 @Override triggerFullNetworkRegistration(int sipCode, String sipReason)212 public void triggerFullNetworkRegistration(int sipCode, String sipReason) { 213 try { 214 mImsRegistration.triggerFullNetworkRegistration(sipCode, sipReason); 215 } catch (RemoteException e) { 216 logw("triggerFullNetworkRegistration called on unreachable ImsRegistration:" + e); 217 } 218 } 219 notifySipDelegateCreated(ISipDelegate delegate, List<FeatureTagState> deniedFeatureTags)220 private void notifySipDelegateCreated(ISipDelegate delegate, 221 List<FeatureTagState> deniedFeatureTags) { 222 logi("Delegate Created: " + delegate + ", deniedTags:" + deniedFeatureTags); 223 if (delegate == null) { 224 logw("Invalid null delegate returned!"); 225 } 226 mDelegateBinder = delegate; 227 // Add denied feature tags from SipDelegate to the ones denied by the transport 228 if (deniedFeatureTags != null) { 229 mDeniedTags.addAll(deniedFeatureTags); 230 } 231 if (mPendingCreatedConsumer == null) return; 232 mPendingCreatedConsumer.accept(delegate, mDeniedTags); 233 mPendingCreatedConsumer = null; 234 } 235 notifySipDelegateDestroyed(int reason)236 private void notifySipDelegateDestroyed(int reason) { 237 logi("Delegate Destroyed, reason: " + reason); 238 mDelegateBinder = null; 239 if (mPendingDestroyedConsumer == null) return; 240 mPendingDestroyedConsumer.accept(reason); 241 mPendingDestroyedConsumer = null; 242 } 243 244 /** Dump state about this binder connection that should be included in the dumpsys. */ dump(PrintWriter printWriter)245 public void dump(PrintWriter printWriter) { 246 mLocalLog.dump(printWriter); 247 } 248 logi(String log)249 protected final void logi(String log) { 250 Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log); 251 mLocalLog.log("[I] " + log); 252 } 253 logw(String log)254 protected final void logw(String log) { 255 Log.w(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log); 256 mLocalLog.log("[W] " + log); 257 } 258 259 @Override binderDied()260 public void binderDied() { 261 mExecutor.execute(() -> { 262 logw("binderDied!"); 263 // Unblock any pending create/destroy operations. 264 // SipTransportController will handle the overall destruction/teardown. 265 notifySipDelegateCreated(null, Collections.emptyList()); 266 notifySipDelegateDestroyed(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD); 267 }); 268 } 269 } 270