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