• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.internal.telephony;
18 
19 import android.net.KeepalivePacketData;
20 import android.net.LinkProperties;
21 import android.os.AsyncResult;
22 import android.os.Message;
23 import android.os.RemoteException;
24 import android.telephony.Rlog;
25 import android.telephony.ServiceState;
26 import android.telephony.data.DataProfile;
27 import android.telephony.data.DataService;
28 import android.telephony.data.NetworkSliceInfo;
29 import android.telephony.data.TrafficDescriptor;
30 
31 import java.net.Inet4Address;
32 import java.net.Inet6Address;
33 import java.net.InetAddress;
34 import java.util.ArrayList;
35 
36 /**
37  * A holder for IRadioData. Use getHidl to get IRadio 1.0 and call the HIDL implementations or
38  * getAidl to get IRadioData and call the AIDL implementations of the HAL APIs.
39  */
40 public class RadioDataProxy extends RadioServiceProxy {
41     private static final String TAG = "RadioDataProxy";
42     private volatile android.hardware.radio.data.IRadioData mDataProxy = null;
43 
44     /**
45      * Set IRadioData as the AIDL implementation for RadioServiceProxy
46      * @param halVersion Radio HAL version
47      * @param data IRadioData implementation
48      *
49      * @return updated HAL version
50      */
setAidl(HalVersion halVersion, android.hardware.radio.data.IRadioData data)51     public HalVersion setAidl(HalVersion halVersion, android.hardware.radio.data.IRadioData data) {
52         HalVersion version = halVersion;
53         try {
54             version = RIL.getServiceHalVersion(data.getInterfaceVersion());
55         } catch (RemoteException e) {
56             Rlog.e(TAG, "setAidl: " + e);
57         }
58         mHalVersion = version;
59         mDataProxy = data;
60         mIsAidl = true;
61 
62         Rlog.d(TAG, "AIDL initialized mHalVersion=" + mHalVersion);
63         return mHalVersion;
64     }
65 
66     /**
67      * Get the AIDL implementation of RadioDataProxy
68      * @return IRadioData implementation
69      */
getAidl()70     public android.hardware.radio.data.IRadioData getAidl() {
71         return mDataProxy;
72     }
73 
74     /**
75      * Reset RadioDataProxy
76      */
77     @Override
clear()78     public void clear() {
79         super.clear();
80         mDataProxy = null;
81     }
82 
83     /**
84      * Check whether a RadioData implementation exists
85      * @return true if there is neither a HIDL nor AIDL implementation
86      */
87     @Override
isEmpty()88     public boolean isEmpty() {
89         return mRadioProxy == null && mDataProxy == null;
90     }
91 
92     /**
93      * Call IRadioData#allocatePduSessionId
94      * @param serial Serial number of request
95      * @throws RemoteException
96      */
allocatePduSessionId(int serial)97     public void allocatePduSessionId(int serial) throws RemoteException {
98         if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
99         if (isAidl()) {
100             mDataProxy.allocatePduSessionId(serial);
101         } else {
102             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).allocatePduSessionId(serial);
103         }
104     }
105 
106     /**
107      * Call IRadioData#cancelHandover
108      * @param serial Serial number of request
109      * @param callId Identifier associated with the data call
110      * @throws RemoteException
111      */
cancelHandover(int serial, int callId)112     public void cancelHandover(int serial, int callId) throws RemoteException {
113         if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
114         if (isAidl()) {
115             mDataProxy.cancelHandover(serial, callId);
116         } else {
117             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).cancelHandover(serial, callId);
118         }
119     }
120 
121     /**
122      * Call IRadioData#deactivateDataCall
123      * @param serial Serial number of request
124      * @param cid The connection ID
125      * @param reason Data disconnect reason
126      * @throws RemoteException
127      */
deactivateDataCall(int serial, int cid, int reason)128     public void deactivateDataCall(int serial, int cid, int reason) throws RemoteException {
129         if (isEmpty()) return;
130         if (isAidl()) {
131             mDataProxy.deactivateDataCall(serial, cid, reason);
132         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_2)) {
133             ((android.hardware.radio.V1_2.IRadio) mRadioProxy).deactivateDataCall_1_2(
134                     serial, cid, reason);
135         } else {
136             mRadioProxy.deactivateDataCall(serial, cid,
137                     reason == DataService.REQUEST_REASON_SHUTDOWN);
138         }
139     }
140 
141     /**
142      * Call IRadioData#getDataCallList
143      * @param serial Serial number of request
144      * @throws RemoteException
145      */
getDataCallList(int serial)146     public void getDataCallList(int serial) throws RemoteException {
147         if (isEmpty()) return;
148         if (isAidl()) {
149             mDataProxy.getDataCallList(serial);
150         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) {
151             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).getDataCallList_1_6(serial);
152         } else {
153             mRadioProxy.getDataCallList(serial);
154         }
155     }
156 
157     /**
158      * Call IRadioData#getSlicingConfig
159      * @param serial Serial number of request
160      * @throws RemoteException
161      */
getSlicingConfig(int serial)162     public void getSlicingConfig(int serial) throws RemoteException {
163         if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
164         if (isAidl()) {
165             mDataProxy.getSlicingConfig(serial);
166         } else {
167             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).getSlicingConfig(serial);
168         }
169     }
170 
171     /**
172      * Call IRadioData#releasePduSessionId
173      * @param serial Serial number of request
174      * @param id PDU session ID to release
175      * @throws RemoteException
176      */
releasePduSessionId(int serial, int id)177     public void releasePduSessionId(int serial, int id) throws RemoteException {
178         if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
179         if (isAidl()) {
180             mDataProxy.releasePduSessionId(serial, id);
181         } else {
182             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).releasePduSessionId(serial, id);
183         }
184     }
185 
186     /**
187      * Call IRadioData#responseAcknowledgement
188      * @throws RemoteException
189      */
190     @Override
responseAcknowledgement()191     public void responseAcknowledgement() throws RemoteException {
192         if (isEmpty()) return;
193         if (isAidl()) {
194             mDataProxy.responseAcknowledgement();
195         } else {
196             mRadioProxy.responseAcknowledgement();
197         }
198     }
199 
200     /**
201      * Call IRadioData#setDataAllowed
202      * @param serial Serial number of request
203      * @param allow Whether to allow or disallow data calls
204      * @throws RemoteException
205      */
setDataAllowed(int serial, boolean allow)206     public void setDataAllowed(int serial, boolean allow) throws RemoteException {
207         if (isEmpty()) return;
208         if (isAidl()) {
209             mDataProxy.setDataAllowed(serial, allow);
210         } else {
211             mRadioProxy.setDataAllowed(serial, allow);
212         }
213     }
214 
215     /**
216      * Call IRadioData#setDataProfile
217      * @param serial Serial number of request
218      * @param profiles Array of DataProfiles to set
219      * @param isRoaming Whether or not the device is roaming
220      * @throws RemoteException
221      */
setDataProfile(int serial, DataProfile[] profiles, boolean isRoaming)222     public void setDataProfile(int serial, DataProfile[] profiles, boolean isRoaming)
223             throws RemoteException {
224         if (isEmpty()) return;
225         if (isAidl()) {
226             android.hardware.radio.data.DataProfileInfo[] dpis =
227                     new android.hardware.radio.data.DataProfileInfo[profiles.length];
228             for (int i = 0; i < profiles.length; i++) {
229                 dpis[i] = RILUtils.convertToHalDataProfile(profiles[i]);
230             }
231             mDataProxy.setDataProfile(serial, dpis);
232         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
233             ArrayList<android.hardware.radio.V1_5.DataProfileInfo> dpis = new ArrayList<>();
234             for (DataProfile dp : profiles) {
235                 dpis.add(RILUtils.convertToHalDataProfile15(dp));
236             }
237             ((android.hardware.radio.V1_5.IRadio) mRadioProxy).setDataProfile_1_5(serial, dpis);
238         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_4)) {
239             ArrayList<android.hardware.radio.V1_4.DataProfileInfo> dpis = new ArrayList<>();
240             for (DataProfile dp : profiles) {
241                 dpis.add(RILUtils.convertToHalDataProfile14(dp));
242             }
243             ((android.hardware.radio.V1_4.IRadio) mRadioProxy).setDataProfile_1_4(serial, dpis);
244         } else {
245             ArrayList<android.hardware.radio.V1_0.DataProfileInfo> dpis = new ArrayList<>();
246             for (DataProfile dp : profiles) {
247                 if (dp.isPersistent()) {
248                     dpis.add(RILUtils.convertToHalDataProfile10(dp));
249                 }
250             }
251             if (!dpis.isEmpty()) {
252                 mRadioProxy.setDataProfile(serial, dpis, isRoaming);
253             }
254         }
255     }
256 
257     /**
258      * Call IRadioData#setDataThrottling
259      * @param serial Serial number of request
260      * @param dataThrottlingAction DataThrottlingAction as defined in DataThrottlingAction.aidl
261      * @param completionDurationMillis Window in ms in which the requested throttling action has to
262      *                                 be achieved.
263      * @throws RemoteException
264      */
setDataThrottling(int serial, byte dataThrottlingAction, long completionDurationMillis)265     public void setDataThrottling(int serial, byte dataThrottlingAction,
266             long completionDurationMillis) throws RemoteException {
267         if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
268         if (isAidl()) {
269             mDataProxy.setDataThrottling(serial, dataThrottlingAction, completionDurationMillis);
270         } else {
271             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).setDataThrottling(serial,
272                     dataThrottlingAction, completionDurationMillis);
273         }
274     }
275 
276     /**
277      * Call IRadioData#setInitialAttachApn
278      * @param serial Serial number of request
279      * @param dataProfile Data profile containing APN settings
280      * @param isRoaming Whether or not the device is roaming
281      * @throws RemoteException
282      */
setInitialAttachApn(int serial, DataProfile dataProfile, boolean isRoaming)283     public void setInitialAttachApn(int serial, DataProfile dataProfile, boolean isRoaming)
284             throws RemoteException {
285         if (isEmpty()) return;
286         if (isAidl()) {
287             mDataProxy.setInitialAttachApn(serial, RILUtils.convertToHalDataProfile(dataProfile));
288         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
289             ((android.hardware.radio.V1_5.IRadio) mRadioProxy).setInitialAttachApn_1_5(serial,
290                     RILUtils.convertToHalDataProfile15(dataProfile));
291         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_4)) {
292             ((android.hardware.radio.V1_4.IRadio) mRadioProxy).setInitialAttachApn_1_4(serial,
293                     RILUtils.convertToHalDataProfile14(dataProfile));
294         } else {
295             mRadioProxy.setInitialAttachApn(serial, RILUtils.convertToHalDataProfile10(dataProfile),
296                     dataProfile.isPersistent(), isRoaming);
297         }
298     }
299 
300     /**
301      * Call IRadioData#setupDataCall
302      * @param serial Serial number of request
303      * @param phoneId Phone ID of the requestor
304      * @param accessNetwork Access network to setup the data call
305      * @param dataProfileInfo Data profile info
306      * @param isRoaming Whether or not the device is roaming
307      * @param roamingAllowed Whether or not data roaming is allowed by the user
308      * @param reason Request reason
309      * @param linkProperties LinkProperties containing address and DNS info
310      * @param pduSessionId The PDU session ID to be used for this data call
311      * @param sliceInfo SliceInfo to be used for the data connection when a handover occurs from
312      *                  EPDG to 5G
313      * @param trafficDescriptor TrafficDescriptor for which the data connection needs to be
314      *                          established
315      * @param matchAllRuleAllowed Whether or not the default match-all URSP rule for this request
316      *                            is allowed
317      * @throws RemoteException
318      */
setupDataCall(int serial, int phoneId, int accessNetwork, DataProfile dataProfileInfo, boolean isRoaming, boolean roamingAllowed, int reason, LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed)319     public void setupDataCall(int serial, int phoneId, int accessNetwork,
320             DataProfile dataProfileInfo, boolean isRoaming, boolean roamingAllowed, int reason,
321             LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo,
322             TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed)
323             throws RemoteException {
324         if (isEmpty()) return;
325         ArrayList<String> addresses = new ArrayList<>();
326         ArrayList<String> dnses = new ArrayList<>();
327         String[] dnsesArr = null;
328         if (linkProperties != null) {
329             for (InetAddress address : linkProperties.getAddresses()) {
330                 addresses.add(address.getHostAddress());
331             }
332             dnsesArr = new String[linkProperties.getDnsServers().size()];
333             for (int i = 0; i < linkProperties.getDnsServers().size(); i++) {
334                 dnses.add(linkProperties.getDnsServers().get(i).getHostAddress());
335                 dnsesArr[i] = linkProperties.getDnsServers().get(i).getHostAddress();
336             }
337         } else {
338             dnsesArr = new String[0];
339         }
340         if (isAidl()) {
341             // Create a new DataProfile to set the TrafficDescriptor
342             DataProfile dp = new DataProfile.Builder()
343                     .setType(dataProfileInfo.getType())
344                     .setPreferred(dataProfileInfo.isPreferred())
345                     .setTrafficDescriptor(trafficDescriptor)
346                     .setApnSetting(dataProfileInfo.getApnSetting())
347                     .build();
348             mDataProxy.setupDataCall(serial, accessNetwork, RILUtils.convertToHalDataProfile(dp),
349                     roamingAllowed, reason, RILUtils.convertToHalLinkProperties(linkProperties),
350                     dnsesArr, pduSessionId, RILUtils.convertToHalSliceInfoAidl(sliceInfo),
351                     matchAllRuleAllowed);
352         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) {
353             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).setupDataCall_1_6(serial,
354                     accessNetwork, RILUtils.convertToHalDataProfile15(dataProfileInfo),
355                     roamingAllowed, reason, RILUtils.convertToHalLinkProperties15(linkProperties),
356                     dnses, pduSessionId, RILUtils.convertToHalSliceInfo(sliceInfo),
357                     RILUtils.convertToHalTrafficDescriptor(trafficDescriptor),
358                     matchAllRuleAllowed);
359         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) {
360             ((android.hardware.radio.V1_5.IRadio) mRadioProxy).setupDataCall_1_5(serial,
361                     accessNetwork, RILUtils.convertToHalDataProfile15(dataProfileInfo),
362                     roamingAllowed, reason, RILUtils.convertToHalLinkProperties15(linkProperties),
363                     dnses);
364         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_4)) {
365             ((android.hardware.radio.V1_4.IRadio) mRadioProxy).setupDataCall_1_4(serial,
366                     accessNetwork, RILUtils.convertToHalDataProfile14(dataProfileInfo),
367                     roamingAllowed, reason, addresses, dnses);
368         } else if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_2)) {
369             ((android.hardware.radio.V1_2.IRadio) mRadioProxy).setupDataCall_1_2(serial,
370                     accessNetwork, RILUtils.convertToHalDataProfile10(dataProfileInfo),
371                     dataProfileInfo.isPersistent(), roamingAllowed, isRoaming, reason, addresses,
372                     dnses);
373         } else {
374             // Getting data RAT here is just a workaround to support the older 1.0 vendor RIL.
375             // The new data service interface passes access network type instead of RAT for
376             // setup data request. It is impossible to convert access network type back to RAT here,
377             // so we directly get the data RAT from phone.
378             int dataRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
379             Phone phone = PhoneFactory.getPhone(phoneId);
380             if (phone != null) {
381                 ServiceState ss = phone.getServiceState();
382                 if (ss != null) {
383                     dataRat = ss.getRilDataRadioTechnology();
384                 }
385             }
386             mRadioProxy.setupDataCall(serial, dataRat,
387                     RILUtils.convertToHalDataProfile10(dataProfileInfo),
388                     dataProfileInfo.isPersistent(), roamingAllowed, isRoaming);
389         }
390     }
391 
392     /**
393      * Call IRadioData#startHandover
394      * @param serial Serial number of request
395      * @param callId Identifier of the data call
396      * @throws RemoteException
397      */
startHandover(int serial, int callId)398     public void startHandover(int serial, int callId) throws RemoteException {
399         if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_6)) return;
400         if (isAidl()) {
401             mDataProxy.startHandover(serial, callId);
402         } else {
403             ((android.hardware.radio.V1_6.IRadio) mRadioProxy).startHandover(serial, callId);
404         }
405     }
406 
407     /**
408      * Call IRadioData#startKeepalive
409      * @param serial Serial number of request
410      * @param contextId Context ID for the data call
411      * @param packetData Keepalive packet data
412      * @param intervalMillis Max keepalive interval in ms
413      * @param result Result to return in case of invalid arguments
414      * @throws RemoteException
415      */
startKeepalive(int serial, int contextId, KeepalivePacketData packetData, int intervalMillis, Message result)416     public void startKeepalive(int serial, int contextId, KeepalivePacketData packetData,
417             int intervalMillis, Message result) throws RemoteException {
418         if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_1)) return;
419         if (isAidl()) {
420             android.hardware.radio.data.KeepaliveRequest req =
421                     new android.hardware.radio.data.KeepaliveRequest();
422             req.cid = contextId;
423 
424             if (packetData.getDstAddress() instanceof Inet4Address) {
425                 req.type = android.hardware.radio.data.KeepaliveRequest.TYPE_NATT_IPV4;
426             } else if (packetData.getDstAddress() instanceof Inet6Address) {
427                 req.type = android.hardware.radio.data.KeepaliveRequest.TYPE_NATT_IPV6;
428             } else {
429                 AsyncResult.forMessage(result, null,
430                         CommandException.fromRilErrno(RILConstants.INVALID_ARGUMENTS));
431                 result.sendToTarget();
432                 return;
433             }
434 
435             final InetAddress srcAddress = packetData.getSrcAddress();
436             final InetAddress dstAddress = packetData.getDstAddress();
437             byte[] sourceAddress = new byte[srcAddress.getAddress().length];
438             for (int i = 0; i < sourceAddress.length; i++) {
439                 sourceAddress[i] = srcAddress.getAddress()[i];
440             }
441             req.sourceAddress = sourceAddress;
442             req.sourcePort = packetData.getSrcPort();
443             byte[] destinationAddress = new byte[dstAddress.getAddress().length];
444             for (int i = 0; i < destinationAddress.length; i++) {
445                 destinationAddress[i] = dstAddress.getAddress()[i];
446             }
447             req.destinationAddress = destinationAddress;
448             req.destinationPort = packetData.getDstPort();
449             req.maxKeepaliveIntervalMillis = intervalMillis;
450 
451             mDataProxy.startKeepalive(serial, req);
452         } else {
453             android.hardware.radio.V1_1.KeepaliveRequest req =
454                     new android.hardware.radio.V1_1.KeepaliveRequest();
455 
456             req.cid = contextId;
457 
458             if (packetData.getDstAddress() instanceof Inet4Address) {
459                 req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV4;
460             } else if (packetData.getDstAddress() instanceof Inet6Address) {
461                 req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV6;
462             } else {
463                 AsyncResult.forMessage(result, null,
464                         CommandException.fromRilErrno(RILConstants.INVALID_ARGUMENTS));
465                 result.sendToTarget();
466                 return;
467             }
468 
469             final InetAddress srcAddress = packetData.getSrcAddress();
470             final InetAddress dstAddress = packetData.getDstAddress();
471             RILUtils.appendPrimitiveArrayToArrayList(
472                     srcAddress.getAddress(), req.sourceAddress);
473             req.sourcePort = packetData.getSrcPort();
474             RILUtils.appendPrimitiveArrayToArrayList(
475                     dstAddress.getAddress(), req.destinationAddress);
476             req.destinationPort = packetData.getDstPort();
477             req.maxKeepaliveIntervalMillis = intervalMillis;
478 
479             ((android.hardware.radio.V1_1.IRadio) mRadioProxy).startKeepalive(serial, req);
480         }
481     }
482 
483     /**
484      * Call IRadioData#stopKeepalive
485      * @param serial Serial number of request
486      * @param sessionHandle The handle that was provided by startKeepaliveResponse
487      * @throws RemoteException
488      */
stopKeepalive(int serial, int sessionHandle)489     public void stopKeepalive(int serial, int sessionHandle) throws RemoteException {
490         if (isEmpty() || mHalVersion.less(RIL.RADIO_HAL_VERSION_1_1)) return;
491         if (isAidl()) {
492             mDataProxy.stopKeepalive(serial, sessionHandle);
493         } else {
494             ((android.hardware.radio.V1_1.IRadio) mRadioProxy).stopKeepalive(serial, sessionHandle);
495         }
496     }
497 }
498