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 */
16
17package com.android.internal.telephony.gsm;
18
19import android.os.Message;
20import android.util.Log;
21import android.util.Patterns;
22import android.text.TextUtils;
23
24import com.android.internal.telephony.DataConnection;
25import com.android.internal.telephony.DataConnectionTracker;
26import com.android.internal.telephony.PhoneBase;
27import com.android.internal.telephony.PhoneConstants;
28import com.android.internal.telephony.RILConstants;
29import com.android.internal.telephony.RetryManager;
30
31import java.io.FileDescriptor;
32import java.io.PrintWriter;
33
34/**
35 * {@hide}
36 */
37public class GsmDataConnection extends DataConnection {
38
39    private static final String LOG_TAG = "GSM";
40
41    //***** Instance Variables
42    protected int mProfileId = RILConstants.DATA_PROFILE_DEFAULT;
43    //***** Constructor
44    private GsmDataConnection(PhoneBase phone, String name, int id, RetryManager rm,
45            DataConnectionTracker dct) {
46        super(phone, name, id, rm, dct);
47    }
48
49    /**
50     * Create the connection object
51     *
52     * @param phone the Phone
53     * @param id the connection id
54     * @param rm the RetryManager
55     * @return GsmDataConnection that was created.
56     */
57    static GsmDataConnection makeDataConnection(PhoneBase phone, int id, RetryManager rm,
58            DataConnectionTracker dct) {
59        GsmDataConnection gsmDc = new GsmDataConnection(phone,
60                "GsmDC-" + mCount.incrementAndGet(), id, rm, dct);
61        gsmDc.start();
62        if (DBG) gsmDc.log("Made " + gsmDc.getName());
63        return gsmDc;
64    }
65
66    /**
67     * Begin setting up a data connection, calls setupDataCall
68     * and the ConnectionParams will be returned with the
69     * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj.
70     *
71     * @param cp is the connection parameters
72     */
73    @Override
74    protected
75    void onConnect(ConnectionParams cp) {
76        mApn = cp.apn;
77
78        if (DBG) log("Connecting to carrier: '" + mApn.carrier
79                + "' APN: '" + mApn.apn
80                + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
81
82        createTime = -1;
83        lastFailTime = -1;
84        lastFailCause = FailCause.NONE;
85
86        // msg.obj will be returned in AsyncResult.userObj;
87        Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
88        msg.obj = cp;
89
90        int authType = mApn.authType;
91        if (authType == -1) {
92            authType = TextUtils.isEmpty(mApn.user) ? RILConstants.SETUP_DATA_AUTH_NONE
93                    : RILConstants.SETUP_DATA_AUTH_PAP_CHAP;
94        }
95
96        String protocol;
97        if (phone.getServiceState().getRoaming()) {
98            protocol = mApn.roamingProtocol;
99        } else {
100            protocol = mApn.protocol;
101        }
102
103        phone.mCM.setupDataCall(
104                Integer.toString(getRilRadioTechnology(RILConstants.SETUP_DATA_TECH_GSM)),
105                Integer.toString(mProfileId),
106                mApn.apn, mApn.user, mApn.password,
107                Integer.toString(authType),
108                protocol, msg);
109    }
110
111    public void setProfileId(int profileId) {
112        mProfileId = profileId;
113    }
114
115    public int getProfileId() {
116        return mProfileId;
117    }
118
119    @Override
120    public String toString() {
121        return "{" + getName() + ": State=" + getCurrentState().getName() +
122                " apnSetting=" + mApn + " apnList= " + mApnList + " RefCount=" + mRefCount +
123                " cid=" + cid + " create=" + createTime + " lastFail=" + lastFailTime +
124                " lastFailCause=" + lastFailCause + "}";
125    }
126
127    @Override
128    protected boolean isDnsOk(String[] domainNameServers) {
129        if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
130                && !phone.isDnsCheckDisabled()) {
131            // Work around a race condition where QMI does not fill in DNS:
132            // Deactivate PDP and let DataConnectionTracker retry.
133            // Do not apply the race condition workaround for MMS APN
134            // if Proxy is an IP-address.
135            // Otherwise, the default APN will not be restored anymore.
136            if (!mApn.types[0].equals(PhoneConstants.APN_TYPE_MMS)
137                || !isIpAddress(mApn.mmsProxy)) {
138                log(String.format(
139                        "isDnsOk: return false apn.types[0]=%s APN_TYPE_MMS=%s isIpAddress(%s)=%s",
140                        mApn.types[0], PhoneConstants.APN_TYPE_MMS, mApn.mmsProxy,
141                        isIpAddress(mApn.mmsProxy)));
142                return false;
143            }
144        }
145        return true;
146    }
147
148    @Override
149    protected void log(String s) {
150        Log.d(LOG_TAG, "[" + getName() + "] " + s);
151    }
152
153    private boolean isIpAddress(String address) {
154        if (address == null) return false;
155
156        return Patterns.IP_ADDRESS.matcher(address).matches();
157    }
158
159    @Override
160    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
161        pw.println("GsmDataConnection extends:");
162        super.dump(fd, pw, args);
163        pw.println(" mProfileId=" + mProfileId);
164    }
165}
166