1/*
2 * Copyright (C) 2006 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 */
16package com.android.internal.telephony.dataconnection;
17
18import static com.android.internal.telephony.DctConstants.APN_CBS_ID;
19import static com.android.internal.telephony.DctConstants.APN_DEFAULT_ID;
20import static com.android.internal.telephony.DctConstants.APN_DUN_ID;
21import static com.android.internal.telephony.DctConstants.APN_EMERGENCY_ID;
22import static com.android.internal.telephony.DctConstants.APN_FOTA_ID;
23import static com.android.internal.telephony.DctConstants.APN_IA_ID;
24import static com.android.internal.telephony.DctConstants.APN_IMS_ID;
25import static com.android.internal.telephony.DctConstants.APN_INVALID_ID;
26import static com.android.internal.telephony.DctConstants.APN_MMS_ID;
27import static com.android.internal.telephony.DctConstants.APN_SUPL_ID;
28
29import android.content.Context;
30import android.net.NetworkCapabilities;
31import android.net.NetworkConfig;
32import android.net.NetworkRequest;
33import android.telephony.Rlog;
34
35import java.util.HashMap;
36
37public class DcRequest implements Comparable<DcRequest> {
38    private static final String LOG_TAG = "DcRequest";
39
40    public final NetworkRequest networkRequest;
41    public final int priority;
42    public final int apnId;
43
44    public DcRequest(NetworkRequest nr, Context context) {
45        initApnPriorities(context);
46        networkRequest = nr;
47        apnId = apnIdForNetworkRequest(networkRequest);
48        priority = priorityForApnId(apnId);
49    }
50
51    public String toString() {
52        return networkRequest.toString() + ", priority=" + priority + ", apnId=" + apnId;
53    }
54
55    public int hashCode() {
56        return networkRequest.hashCode();
57    }
58
59    public boolean equals(Object o) {
60        if (o instanceof DcRequest) {
61            return networkRequest.equals(((DcRequest)o).networkRequest);
62        }
63        return false;
64    }
65
66    public int compareTo(DcRequest o) {
67        return o.priority - priority;
68    }
69
70    private int apnIdForNetworkRequest(NetworkRequest nr) {
71        NetworkCapabilities nc = nr.networkCapabilities;
72        // For now, ignore the bandwidth stuff
73        if (nc.getTransportTypes().length > 0 &&
74                nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == false) {
75            return APN_INVALID_ID;
76        }
77
78        // in the near term just do 1-1 matches.
79        // TODO - actually try to match the set of capabilities
80        int apnId = APN_INVALID_ID;
81
82        boolean error = false;
83        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
84            if (apnId != APN_INVALID_ID) error = true;
85            apnId = APN_DEFAULT_ID;
86        }
87        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
88            if (apnId != APN_INVALID_ID) error = true;
89            apnId = APN_MMS_ID;
90        }
91        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
92            if (apnId != APN_INVALID_ID) error = true;
93            apnId = APN_SUPL_ID;
94        }
95        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
96            if (apnId != APN_INVALID_ID) error = true;
97            apnId = APN_DUN_ID;
98        }
99        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
100            if (apnId != APN_INVALID_ID) error = true;
101            apnId = APN_FOTA_ID;
102        }
103        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
104            if (apnId != APN_INVALID_ID) error = true;
105            apnId = APN_IMS_ID;
106        }
107        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
108            if (apnId != APN_INVALID_ID) error = true;
109            apnId = APN_CBS_ID;
110        }
111        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)) {
112            if (apnId != APN_INVALID_ID) error = true;
113            apnId = APN_IA_ID;
114        }
115        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_RCS)) {
116            if (apnId != APN_INVALID_ID) error = true;
117            apnId = APN_INVALID_ID;
118            loge("RCS APN type not yet supported");
119        }
120        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)) {
121            if (apnId != APN_INVALID_ID) error = true;
122            apnId = APN_INVALID_ID;
123            loge("XCAP APN type not yet supported");
124        }
125        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) {
126            if (apnId != APN_INVALID_ID) error = true;
127            apnId = APN_EMERGENCY_ID;
128        }
129        if (error) {
130            // TODO: If this error condition is removed, the framework's handling of
131            // NET_CAPABILITY_NOT_RESTRICTED will need to be updated so requests for
132            // say FOTA and INTERNET are marked as restricted.  This is not how
133            // NetworkCapabilities.maybeMarkCapabilitiesRestricted currently works.
134            loge("Multiple apn types specified in request - result is unspecified!");
135        }
136        if (apnId == APN_INVALID_ID) {
137            loge("Unsupported NetworkRequest in Telephony: nr=" + nr);
138        }
139        return apnId;
140    }
141
142    private static final HashMap<Integer, Integer> sApnPriorityMap =
143            new HashMap<Integer, Integer>();
144
145    private void initApnPriorities(Context context) {
146        synchronized (sApnPriorityMap) {
147            if (sApnPriorityMap.isEmpty()) {
148                String[] networkConfigStrings = context.getResources().getStringArray(
149                        com.android.internal.R.array.networkAttributes);
150                for (String networkConfigString : networkConfigStrings) {
151                    NetworkConfig networkConfig = new NetworkConfig(networkConfigString);
152                    final int apnId = ApnContext.apnIdForType(networkConfig.type);
153                    sApnPriorityMap.put(apnId, networkConfig.priority);
154                }
155            }
156        }
157    }
158
159    private int priorityForApnId(int apnId) {
160        Integer priority = sApnPriorityMap.get(apnId);
161        return (priority != null ? priority.intValue() : 0);
162    }
163
164    private void loge(String s) {
165        Rlog.e(LOG_TAG, s);
166    }
167}
168