1 /* 2 * Copyright (C) 2021 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 android.telephony.mockmodem; 18 19 import android.content.Context; 20 import android.hardware.radio.RadioError; 21 import android.hardware.radio.RadioIndicationType; 22 import android.hardware.radio.RadioResponseInfo; 23 import android.hardware.radio.data.DataProfileInfo; 24 import android.hardware.radio.data.IRadioData; 25 import android.hardware.radio.data.IRadioDataIndication; 26 import android.hardware.radio.data.IRadioDataResponse; 27 import android.hardware.radio.data.KeepaliveRequest; 28 import android.hardware.radio.data.LinkAddress; 29 import android.hardware.radio.data.SetupDataCallResult; 30 import android.hardware.radio.data.SliceInfo; 31 import android.os.AsyncResult; 32 import android.os.Handler; 33 import android.os.Message; 34 import android.os.RemoteException; 35 import android.util.Log; 36 37 import java.util.List; 38 39 public class IRadioDataImpl extends IRadioData.Stub { 40 private static final String TAG = "MRDATA"; 41 42 private final MockModemService mService; 43 private final MockDataService mMockDataService; 44 private IRadioDataResponse mRadioDataResponse; 45 private IRadioDataIndication mRadioDataIndication; 46 private MockModemConfigInterface mMockModemConfigInterface; 47 private static Object sCacheUpdateMutex = new Object(); 48 private final Handler mHandler; 49 private int mSubId; 50 private String mTag; 51 52 private static MockNetworkService sServiceState; 53 54 // Event 55 static final int EVENT_NETWORK_STATUS_CHANGED = 1; 56 IRadioDataImpl( MockModemService service, Context context, MockModemConfigInterface configInterface, int instanceId)57 public IRadioDataImpl( 58 MockModemService service, 59 Context context, 60 MockModemConfigInterface configInterface, 61 int instanceId) { 62 mTag = TAG + "-" + instanceId; 63 Log.d(mTag, "Instantiated"); 64 65 mMockDataService = new MockDataService(context, instanceId); 66 this.mService = service; 67 68 mMockModemConfigInterface = configInterface; 69 mSubId = instanceId; 70 71 mHandler = new IRadioDataHandler(); 72 73 // Register event 74 mMockModemConfigInterface.registerForServiceStateChanged( 75 mSubId, mHandler, EVENT_NETWORK_STATUS_CHANGED, null); 76 } 77 getMockDataServiceInstance()78 public MockDataService getMockDataServiceInstance() { 79 return mMockDataService; 80 } 81 82 // Implementation of IRadioData functions 83 @Override setResponseFunctions( IRadioDataResponse radioDataResponse, IRadioDataIndication radioDataIndication)84 public void setResponseFunctions( 85 IRadioDataResponse radioDataResponse, IRadioDataIndication radioDataIndication) { 86 Log.d(mTag, "setResponseFunctions"); 87 mRadioDataResponse = radioDataResponse; 88 mRadioDataIndication = radioDataIndication; 89 mService.countDownLatch(MockModemService.LATCH_RADIO_INTERFACES_READY); 90 91 unsolDataCallListChanged(); 92 } 93 94 @Override allocatePduSessionId(int serial)95 public void allocatePduSessionId(int serial) { 96 Log.d(mTag, "allocatePduSessionId"); 97 int id = 0; 98 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 99 try { 100 mRadioDataResponse.allocatePduSessionIdResponse(rsp, id); 101 } catch (RemoteException ex) { 102 Log.e(mTag, "Failed to allocatePduSessionId from AIDL. Exception" + ex); 103 } 104 } 105 106 @Override cancelHandover(int serial, int callId)107 public void cancelHandover(int serial, int callId) { 108 Log.d(mTag, "cancelHandover"); 109 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 110 try { 111 mRadioDataResponse.cancelHandoverResponse(rsp); 112 } catch (RemoteException ex) { 113 Log.e(mTag, "Failed to cancelHandover from AIDL. Exception" + ex); 114 } 115 } 116 117 @Override deactivateDataCall(int serial, int cid, int reason)118 public void deactivateDataCall(int serial, int cid, int reason) { 119 Log.d(mTag, "deactivateDataCall"); 120 121 mMockDataService.deactivateDataCall(cid, reason); 122 RadioResponseInfo rsp = mService.makeSolRsp(serial); 123 try { 124 mRadioDataResponse.deactivateDataCallResponse(rsp); 125 } catch (RemoteException ex) { 126 Log.e(mTag, "Failed to deactivateDataCall from AIDL. Exception" + ex); 127 } 128 // send the data call list changed 129 unsolDataCallListChanged(); 130 } 131 132 @Override getDataCallList(int serial)133 public void getDataCallList(int serial) { 134 Log.d(mTag, "getDataCallList"); 135 136 List<SetupDataCallResult> dataCallLists = mMockDataService.getDataCallList(); 137 SetupDataCallResult[] dcList = new SetupDataCallResult[dataCallLists.size()]; 138 dcList = dataCallLists.toArray(dcList); 139 140 RadioResponseInfo rsp = mService.makeSolRsp(serial); 141 try { 142 mRadioDataResponse.getDataCallListResponse(rsp, dcList); 143 } catch (RemoteException ex) { 144 Log.e(mTag, "Failed to getDataCallList from AIDL. Exception" + ex); 145 } 146 } 147 148 @Override getSlicingConfig(int serial)149 public void getSlicingConfig(int serial) { 150 Log.d(mTag, "getSlicingConfig"); 151 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 152 try { 153 mRadioDataResponse.getSlicingConfigResponse(rsp, null); 154 } catch (RemoteException ex) { 155 Log.e(mTag, "Failed to getSlicingConfig from AIDL. Exception" + ex); 156 } 157 } 158 159 @Override releasePduSessionId(int serial, int id)160 public void releasePduSessionId(int serial, int id) { 161 Log.d(mTag, "releasePduSessionId"); 162 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 163 try { 164 mRadioDataResponse.releasePduSessionIdResponse(rsp); 165 } catch (RemoteException ex) { 166 Log.e(mTag, "Failed to releasePduSessionId from AIDL. Exception" + ex); 167 } 168 } 169 170 @Override responseAcknowledgement()171 public void responseAcknowledgement() { 172 Log.d(mTag, "responseAcknowledgement"); 173 } 174 175 @Override setDataAllowed(int serial, boolean allow)176 public void setDataAllowed(int serial, boolean allow) { 177 Log.d(mTag, "setDataAllowed"); 178 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 179 try { 180 mRadioDataResponse.setDataAllowedResponse(rsp); 181 } catch (RemoteException ex) { 182 Log.e(mTag, "Failed to setDataAllowed from AIDL. Exception" + ex); 183 } 184 } 185 186 @Override setDataProfile(int serial, DataProfileInfo[] profiles)187 public void setDataProfile(int serial, DataProfileInfo[] profiles) { 188 Log.d(mTag, "setDataProfile"); 189 190 // set data profiles to mockdataservice 191 mMockDataService.setDataProfileInfo(profiles); 192 193 RadioResponseInfo rsp = mService.makeSolRsp(serial); 194 try { 195 mRadioDataResponse.setDataProfileResponse(rsp); 196 } catch (RemoteException ex) { 197 Log.e(mTag, "Failed to setDataProfile from AIDL. Exception" + ex); 198 } 199 } 200 201 @Override setDataThrottling( int serial, byte dataThrottlingAction, long completionDurationMillis)202 public void setDataThrottling( 203 int serial, byte dataThrottlingAction, long completionDurationMillis) { 204 Log.d(mTag, "setDataThrottling"); 205 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 206 try { 207 mRadioDataResponse.setDataThrottlingResponse(rsp); 208 } catch (RemoteException ex) { 209 Log.e(mTag, "Failed to setDataThrottling from AIDL. Exception" + ex); 210 } 211 } 212 213 @Override setInitialAttachApn(int serial, DataProfileInfo dataProfileInfo)214 public void setInitialAttachApn(int serial, DataProfileInfo dataProfileInfo) { 215 Log.d(mTag, "setInitialAttachApn"); 216 // set initial attach apn to mockdataservice 217 mMockDataService.setInitialAttachProfile(dataProfileInfo); 218 219 RadioResponseInfo rsp = mService.makeSolRsp(serial); 220 try { 221 mRadioDataResponse.setInitialAttachApnResponse(rsp); 222 } catch (RemoteException ex) { 223 Log.e(mTag, "Failed to setInitialAttachApn from AIDL. Exception" + ex); 224 } 225 } 226 227 @Override setupDataCall( int serial, int accessNetwork, DataProfileInfo dataProfileInfo, boolean roamingAllowed, int reason, LinkAddress[] addresses, String[] dnses, int pduSessionId, SliceInfo sliceInfo, boolean matchAllRuleAllowed)228 public void setupDataCall( 229 int serial, 230 int accessNetwork, 231 DataProfileInfo dataProfileInfo, 232 boolean roamingAllowed, 233 int reason, 234 LinkAddress[] addresses, 235 String[] dnses, 236 int pduSessionId, 237 SliceInfo sliceInfo, 238 boolean matchAllRuleAllowed) { 239 Log.d(mTag, "setupDataCall"); 240 241 RadioResponseInfo rsp; 242 SetupDataCallResult dc = new SetupDataCallResult(); 243 rsp = mService.makeSolRsp(serial); 244 synchronized (sCacheUpdateMutex) { 245 if (sServiceState == null || !sServiceState.isPsInService()) { 246 rsp = mService.makeSolRsp(serial, RadioError.OP_NOT_ALLOWED_BEFORE_REG_TO_NW); 247 } else { 248 if (mMockDataService.isSupportedCapability(dataProfileInfo.apn)) { 249 if (dataProfileInfo.apn.equals("ims")) { 250 dc = mMockDataService.setupDataCall(mMockDataService.APN_TYPE_IMS); 251 } else if (dataProfileInfo.apn.equals("internet")) { 252 dc = mMockDataService.setupDataCall(mMockDataService.APN_TYPE_DEFAULT); 253 } 254 } else { 255 rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 256 } 257 } 258 } 259 260 try { 261 mRadioDataResponse.setupDataCallResponse(rsp, dc); 262 } catch (RemoteException ex) { 263 Log.e(mTag, "Failed to setupDataCall from AIDL. Exception" + ex); 264 } 265 // send the data call list changed 266 unsolDataCallListChanged(); 267 } 268 269 @Override startHandover(int serial, int callId)270 public void startHandover(int serial, int callId) { 271 Log.d(mTag, "startHandover"); 272 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 273 try { 274 mRadioDataResponse.startHandoverResponse(rsp); 275 } catch (RemoteException ex) { 276 Log.e(mTag, "Failed to startHandover from AIDL. Exception" + ex); 277 } 278 } 279 280 @Override startKeepalive(int serial, KeepaliveRequest keepalive)281 public void startKeepalive(int serial, KeepaliveRequest keepalive) { 282 Log.d(mTag, "startKeepalive"); 283 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 284 try { 285 mRadioDataResponse.startKeepaliveResponse(rsp, null); 286 } catch (RemoteException ex) { 287 Log.e(mTag, "Failed to startKeepalive from AIDL. Exception" + ex); 288 } 289 } 290 291 @Override stopKeepalive(int serial, int sessionHandle)292 public void stopKeepalive(int serial, int sessionHandle) { 293 Log.d(mTag, "stopKeepalive"); 294 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 295 try { 296 mRadioDataResponse.stopKeepaliveResponse(rsp); 297 } catch (RemoteException ex) { 298 Log.e(mTag, "Failed to stopKeepalive from AIDL. Exception" + ex); 299 } 300 } 301 302 @Override getInterfaceHash()303 public String getInterfaceHash() { 304 return IRadioData.HASH; 305 } 306 307 @Override getInterfaceVersion()308 public int getInterfaceVersion() { 309 return IRadioData.VERSION; 310 } 311 unsolDataCallListChanged()312 public void unsolDataCallListChanged() { 313 Log.d(mTag, "unsolDataCallListChanged"); 314 315 if (mRadioDataIndication != null) { 316 List<SetupDataCallResult> dataCallLists = mMockDataService.getDataCallList(); 317 SetupDataCallResult[] dcList = new SetupDataCallResult[dataCallLists.size()]; 318 dcList = dataCallLists.toArray(dcList); 319 320 try { 321 mRadioDataIndication.dataCallListChanged(RadioIndicationType.UNSOLICITED, dcList); 322 } catch (RemoteException ex) { 323 Log.e( 324 mTag, 325 "Failed to invoke dataCallListChanged change from AIDL. Exception" + ex); 326 } 327 } else { 328 Log.e(mTag, "null mRadioDataIndication"); 329 } 330 } 331 332 /** Handler class to handle callbacks */ 333 private static final class IRadioDataHandler extends Handler { 334 @Override handleMessage(Message msg)335 public void handleMessage(Message msg) { 336 AsyncResult ar; 337 synchronized (sCacheUpdateMutex) { 338 switch (msg.what) { 339 case EVENT_NETWORK_STATUS_CHANGED: 340 Log.d(TAG, "Received EVENT_NETWORK_STATUS_CHANGED"); 341 ar = (AsyncResult) msg.obj; 342 if (ar != null && ar.exception == null) { 343 sServiceState = (MockNetworkService) ar.result; 344 Log.i(TAG, "Service State: " + sServiceState.toString()); 345 } else { 346 Log.e(TAG, msg.what + " failure. Exception: " + ar.exception); 347 } 348 break; 349 } 350 } 351 } 352 } 353 } 354