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