Home | History | Annotate | Download | only in dataconnection
      1 /*
      2  * Copyright (C) 2011 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.dataconnection;
     18 
     19 import android.net.LinkProperties;
     20 import android.net.NetworkCapabilities;
     21 import android.net.ProxyInfo;
     22 import android.os.Message;
     23 
     24 import com.android.internal.telephony.dataconnection.DataConnection.ConnectionParams;
     25 import com.android.internal.telephony.dataconnection.DataConnection.DisconnectParams;
     26 import com.android.internal.util.AsyncChannel;
     27 import com.android.internal.util.Protocol;
     28 
     29 /**
     30  * AsyncChannel to a DataConnection
     31  */
     32 public class DcAsyncChannel extends AsyncChannel {
     33     private static final boolean DBG = false;
     34     private String mLogTag;
     35 
     36     private DataConnection mDc;
     37     private long mDcThreadId;
     38 
     39     public static final int BASE = Protocol.BASE_DATA_CONNECTION_AC;
     40 
     41     public static final int REQ_IS_INACTIVE = BASE + 0;
     42     public static final int RSP_IS_INACTIVE = BASE + 1;
     43 
     44     public static final int REQ_GET_CID = BASE + 2;
     45     public static final int RSP_GET_CID = BASE + 3;
     46 
     47     public static final int REQ_GET_APNSETTING = BASE + 4;
     48     public static final int RSP_GET_APNSETTING = BASE + 5;
     49 
     50     public static final int REQ_GET_LINK_PROPERTIES = BASE + 6;
     51     public static final int RSP_GET_LINK_PROPERTIES = BASE + 7;
     52 
     53     public static final int REQ_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 8;
     54     public static final int RSP_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 9;
     55 
     56     public static final int REQ_GET_NETWORK_CAPABILITIES = BASE + 10;
     57     public static final int RSP_GET_NETWORK_CAPABILITIES = BASE + 11;
     58 
     59     public static final int REQ_RESET = BASE + 12;
     60     public static final int RSP_RESET = BASE + 13;
     61 
     62     private static final int CMD_TO_STRING_COUNT = RSP_RESET - BASE + 1;
     63     private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
     64     static {
     65         sCmdToString[REQ_IS_INACTIVE - BASE] = "REQ_IS_INACTIVE";
     66         sCmdToString[RSP_IS_INACTIVE - BASE] = "RSP_IS_INACTIVE";
     67         sCmdToString[REQ_GET_CID - BASE] = "REQ_GET_CID";
     68         sCmdToString[RSP_GET_CID - BASE] = "RSP_GET_CID";
     69         sCmdToString[REQ_GET_APNSETTING - BASE] = "REQ_GET_APNSETTING";
     70         sCmdToString[RSP_GET_APNSETTING - BASE] = "RSP_GET_APNSETTING";
     71         sCmdToString[REQ_GET_LINK_PROPERTIES - BASE] = "REQ_GET_LINK_PROPERTIES";
     72         sCmdToString[RSP_GET_LINK_PROPERTIES - BASE] = "RSP_GET_LINK_PROPERTIES";
     73         sCmdToString[REQ_SET_LINK_PROPERTIES_HTTP_PROXY - BASE] =
     74                 "REQ_SET_LINK_PROPERTIES_HTTP_PROXY";
     75         sCmdToString[RSP_SET_LINK_PROPERTIES_HTTP_PROXY - BASE] =
     76                 "RSP_SET_LINK_PROPERTIES_HTTP_PROXY";
     77         sCmdToString[REQ_GET_NETWORK_CAPABILITIES - BASE] = "REQ_GET_NETWORK_CAPABILITIES";
     78         sCmdToString[RSP_GET_NETWORK_CAPABILITIES - BASE] = "RSP_GET_NETWORK_CAPABILITIES";
     79         sCmdToString[REQ_RESET - BASE] = "REQ_RESET";
     80         sCmdToString[RSP_RESET - BASE] = "RSP_RESET";
     81     }
     82 
     83     ConnectionParams mLastConnectionParams;
     84 
     85     // Convert cmd to string or null if unknown
     86     protected static String cmdToString(int cmd) {
     87         cmd -= BASE;
     88         if ((cmd >= 0) && (cmd < sCmdToString.length)) {
     89             return sCmdToString[cmd];
     90         } else {
     91             return AsyncChannel.cmdToString(cmd + BASE);
     92         }
     93     }
     94 
     95     /**
     96      * enum used to notify action taken or necessary to be
     97      * taken after the link property is changed.
     98      */
     99     public enum LinkPropertyChangeAction {
    100         NONE, CHANGED, RESET;
    101 
    102         public static LinkPropertyChangeAction fromInt(int value) {
    103             if (value == NONE.ordinal()) {
    104                 return NONE;
    105             } else if (value == CHANGED.ordinal()) {
    106                 return CHANGED;
    107             } else if (value == RESET.ordinal()) {
    108                 return RESET;
    109             } else {
    110                 throw new RuntimeException("LinkPropertyChangeAction.fromInt: bad value=" + value);
    111             }
    112         }
    113     }
    114 
    115     public DcAsyncChannel(DataConnection dc, String logTag) {
    116         mDc = dc;
    117         mDcThreadId = mDc.getHandler().getLooper().getThread().getId();
    118         mLogTag = logTag;
    119     }
    120 
    121     /**
    122      * Request if the state machine is in the inactive state.
    123      * Response {@link #rspIsInactive}
    124      */
    125     public void reqIsInactive() {
    126         sendMessage(REQ_IS_INACTIVE);
    127         if (DBG) log("reqIsInactive");
    128     }
    129 
    130     /**
    131      * Evaluate RSP_IS_INACTIVE.
    132      *
    133      * @return true if the state machine is in the inactive state.
    134      */
    135     public boolean rspIsInactive(Message response) {
    136         boolean retVal = response.arg1 == 1;
    137         if (DBG) log("rspIsInactive=" + retVal);
    138         return retVal;
    139     }
    140 
    141     /**
    142      * @return true if the state machine is in the inactive state
    143      * and can be used for a new connection.
    144      */
    145     public boolean isInactiveSync() {
    146         boolean value;
    147         if (isCallerOnDifferentThread()) {
    148             Message response = sendMessageSynchronously(REQ_IS_INACTIVE);
    149             if ((response != null) && (response.what == RSP_IS_INACTIVE)) {
    150                 value = rspIsInactive(response);
    151             } else {
    152                 log("rspIsInactive error response=" + response);
    153                 value = false;
    154             }
    155         } else {
    156             value = mDc.isInactive();
    157         }
    158         return value;
    159     }
    160 
    161     /**
    162      * Request the Connection ID.
    163      * Response {@link #rspCid}
    164      */
    165     public void reqCid() {
    166         sendMessage(REQ_GET_CID);
    167         if (DBG) log("reqCid");
    168     }
    169 
    170     /**
    171      * Evaluate a RSP_GET_CID message and return the cid.
    172      *
    173      * @param response Message
    174      * @return connection id or -1 if an error
    175      */
    176     public int rspCid(Message response) {
    177         int retVal = response.arg1;
    178         if (DBG) log("rspCid=" + retVal);
    179         return retVal;
    180     }
    181 
    182     /**
    183      * @return connection id or -1 if an error
    184      */
    185     public int getCidSync() {
    186         int value;
    187         if (isCallerOnDifferentThread()) {
    188             Message response = sendMessageSynchronously(REQ_GET_CID);
    189             if ((response != null) && (response.what == RSP_GET_CID)) {
    190                 value = rspCid(response);
    191             } else {
    192                 log("rspCid error response=" + response);
    193                 value = -1;
    194             }
    195         } else {
    196             value = mDc.getCid();
    197         }
    198         return value;
    199     }
    200 
    201     /**
    202      * Request the connections ApnSetting.
    203      * Response {@link #rspApnSetting}
    204      */
    205     public void reqApnSetting() {
    206         sendMessage(REQ_GET_APNSETTING);
    207         if (DBG) log("reqApnSetting");
    208     }
    209 
    210     /**
    211      * Evaluate a RSP_APN_SETTING message and return the ApnSetting.
    212      *
    213      * @param response Message
    214      * @return ApnSetting, maybe null
    215      */
    216     public ApnSetting rspApnSetting(Message response) {
    217         ApnSetting retVal = (ApnSetting) response.obj;
    218         if (DBG) log("rspApnSetting=" + retVal);
    219         return retVal;
    220     }
    221 
    222     /**
    223      * Get the connections ApnSetting.
    224      *
    225      * @return ApnSetting or null if an error
    226      */
    227     public ApnSetting getApnSettingSync() {
    228         ApnSetting value;
    229         if (isCallerOnDifferentThread()) {
    230             Message response = sendMessageSynchronously(REQ_GET_APNSETTING);
    231             if ((response != null) && (response.what == RSP_GET_APNSETTING)) {
    232                 value = rspApnSetting(response);
    233             } else {
    234                 log("getApnSetting error response=" + response);
    235                 value = null;
    236             }
    237         } else {
    238             value = mDc.getApnSetting();
    239         }
    240         return value;
    241     }
    242 
    243     /**
    244      * Request the connections LinkProperties.
    245      * Response {@link #rspLinkProperties}
    246      */
    247     public void reqLinkProperties() {
    248         sendMessage(REQ_GET_LINK_PROPERTIES);
    249         if (DBG) log("reqLinkProperties");
    250     }
    251 
    252     /**
    253      * Evaluate RSP_GET_LINK_PROPERTIES
    254      *
    255      * @param response
    256      * @return LinkProperties, maybe null.
    257      */
    258     public LinkProperties rspLinkProperties(Message response) {
    259         LinkProperties retVal = (LinkProperties) response.obj;
    260         if (DBG) log("rspLinkProperties=" + retVal);
    261         return retVal;
    262     }
    263 
    264     /**
    265      * Get the connections LinkProperties.
    266      *
    267      * @return LinkProperties or null if an error
    268      */
    269     public LinkProperties getLinkPropertiesSync() {
    270         LinkProperties value;
    271         if (isCallerOnDifferentThread()) {
    272             Message response = sendMessageSynchronously(REQ_GET_LINK_PROPERTIES);
    273             if ((response != null) && (response.what == RSP_GET_LINK_PROPERTIES)) {
    274                 value = rspLinkProperties(response);
    275             } else {
    276                 log("getLinkProperties error response=" + response);
    277                 value = null;
    278             }
    279         } else {
    280             value = mDc.getCopyLinkProperties();
    281         }
    282         return value;
    283     }
    284 
    285     /**
    286      * Request setting the connections LinkProperties.HttpProxy.
    287      * Response RSP_SET_LINK_PROPERTIES when complete.
    288      */
    289     public void reqSetLinkPropertiesHttpProxy(ProxyInfo proxy) {
    290         sendMessage(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
    291         if (DBG) log("reqSetLinkPropertiesHttpProxy proxy=" + proxy);
    292     }
    293 
    294     /**
    295      * Set the connections LinkProperties.HttpProxy
    296      */
    297     public void setLinkPropertiesHttpProxySync(ProxyInfo proxy) {
    298         if (isCallerOnDifferentThread()) {
    299             Message response =
    300                 sendMessageSynchronously(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
    301             if ((response != null) && (response.what == RSP_SET_LINK_PROPERTIES_HTTP_PROXY)) {
    302                 if (DBG) log("setLinkPropertiesHttpPoxy ok");
    303             } else {
    304                 log("setLinkPropertiesHttpPoxy error response=" + response);
    305             }
    306         } else {
    307             mDc.setLinkPropertiesHttpProxy(proxy);
    308         }
    309     }
    310 
    311     /**
    312      * Request the connections NetworkCapabilities.
    313      * Response {@link #rspNetworkCapabilities}
    314      */
    315     public void reqNetworkCapabilities() {
    316         sendMessage(REQ_GET_NETWORK_CAPABILITIES);
    317         if (DBG) log("reqNetworkCapabilities");
    318     }
    319 
    320     /**
    321      * Evaluate RSP_GET_NETWORK_CAPABILITIES
    322      *
    323      * @param response
    324      * @return NetworkCapabilities, maybe null.
    325      */
    326     public NetworkCapabilities rspNetworkCapabilities(Message response) {
    327         NetworkCapabilities retVal = (NetworkCapabilities) response.obj;
    328         if (DBG) log("rspNetworkCapabilities=" + retVal);
    329         return retVal;
    330     }
    331 
    332     /**
    333      * Get the connections NetworkCapabilities.
    334      *
    335      * @return NetworkCapabilities or null if an error
    336      */
    337     public NetworkCapabilities getNetworkCapabilitiesSync() {
    338         NetworkCapabilities value;
    339         if (isCallerOnDifferentThread()) {
    340             Message response = sendMessageSynchronously(REQ_GET_NETWORK_CAPABILITIES);
    341             if ((response != null) && (response.what == RSP_GET_NETWORK_CAPABILITIES)) {
    342                 value = rspNetworkCapabilities(response);
    343             } else {
    344                 value = null;
    345             }
    346         } else {
    347             value = mDc.getNetworkCapabilities();
    348         }
    349         return value;
    350     }
    351 
    352     /**
    353      * Response RSP_RESET when complete
    354      */
    355     public void reqReset() {
    356         sendMessage(REQ_RESET);
    357         if (DBG) log("reqReset");
    358     }
    359 
    360     /**
    361      * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg.
    362      * Used for cellular networks that use Access Point Names (APN) such
    363      * as GSM networks.
    364      *
    365      * @param apnContext is the Access Point Name to bring up a connection to
    366      * @param profileId for the connection
    367      * @param rilRadioTechnology Radio technology for the data connection
    368      * @param unmeteredUseOnly Indicates the data connection can only used for unmetered purposes
    369      * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
    370      *                       With AsyncResult.userObj set to the original msg.obj,
    371      *                       AsyncResult.result = FailCause and AsyncResult.exception = Exception().
    372      * @param connectionGeneration used to track a single connection request so disconnects can get
    373      *                             ignored if obsolete.
    374      */
    375     public void bringUp(ApnContext apnContext, int profileId, int rilRadioTechnology,
    376                         boolean unmeteredUseOnly, Message onCompletedMsg,
    377                         int connectionGeneration) {
    378         if (DBG) {
    379             log("bringUp: apnContext=" + apnContext + "unmeteredUseOnly=" + unmeteredUseOnly
    380                     + " onCompletedMsg=" + onCompletedMsg);
    381         }
    382         mLastConnectionParams = new ConnectionParams(apnContext, profileId, rilRadioTechnology,
    383                 unmeteredUseOnly, onCompletedMsg, connectionGeneration);
    384         sendMessage(DataConnection.EVENT_CONNECT, mLastConnectionParams);
    385     }
    386 
    387     /**
    388      * Tear down the connection through the apn on the network.
    389      *
    390      * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
    391      *        With AsyncResult.userObj set to the original msg.obj.
    392      */
    393     public void tearDown(ApnContext apnContext, String reason, Message onCompletedMsg) {
    394         if (DBG) {
    395             log("tearDown: apnContext=" + apnContext
    396                     + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg);
    397         }
    398         sendMessage(DataConnection.EVENT_DISCONNECT,
    399                         new DisconnectParams(apnContext, reason, onCompletedMsg));
    400     }
    401 
    402     /**
    403      * Tear down the connection through the apn on the network.  Ignores refcount and
    404      * and always tears down.
    405      *
    406      * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
    407      *        With AsyncResult.userObj set to the original msg.obj.
    408      */
    409     public void tearDownAll(String reason, Message onCompletedMsg) {
    410         if (DBG) log("tearDownAll: reason=" + reason + " onCompletedMsg=" + onCompletedMsg);
    411         sendMessage(DataConnection.EVENT_DISCONNECT_ALL,
    412                 new DisconnectParams(null, reason, onCompletedMsg));
    413     }
    414 
    415     /**
    416      * @return connection id
    417      */
    418     public int getDataConnectionIdSync() {
    419         // Safe because this is owned by the caller.
    420         return mDc.getDataConnectionId();
    421     }
    422 
    423     @Override
    424     public String toString() {
    425         return mDc.getName();
    426     }
    427 
    428     private boolean isCallerOnDifferentThread() {
    429         long curThreadId = Thread.currentThread().getId();
    430         boolean value = mDcThreadId != curThreadId;
    431         if (DBG) log("isCallerOnDifferentThread: " + value);
    432         return value;
    433     }
    434 
    435     private void log(String s) {
    436         android.telephony.Rlog.d(mLogTag, "DataConnectionAc " + s);
    437     }
    438 
    439     public String[] getPcscfAddr() {
    440         return mDc.mPcscfAddr;
    441     }
    442 }
    443