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