data activity reporting on wifi

Initial checkin, need icons to complete the feature

Bug: 3412258

Change-Id: I9a3ecc8159cc314d84707065dafe23d402409a84
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index d143243..eca06c5 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -69,6 +69,43 @@
     public static native long getMobileRxBytes();
 
     /**
+     * Get the total number of packets transmitted through the specified interface.
+     *
+     * @return number of packets.  If the statistics are not supported by this interface,
+     * {@link #UNSUPPORTED} will be returned.
+     * @hide
+     */
+    public static native long getTxPackets(String iface);
+
+    /**
+     * Get the total number of packets received through the specified interface.
+     *
+     * @return number of packets.  If the statistics are not supported by this interface,
+     * {@link #UNSUPPORTED} will be returned.
+     * @hide
+     */
+    public static native long getRxPackets(String iface);
+
+    /**
+     * Get the total number of bytes transmitted through the specified interface.
+     *
+     * @return number of bytes.  If the statistics are not supported by this interface,
+     * {@link #UNSUPPORTED} will be returned.
+     * @hide
+     */
+    public static native long getTxBytes(String iface);
+
+    /**
+     * Get the total number of bytes received through the specified interface.
+     *
+     * @return number of bytes.  If the statistics are not supported by this interface,
+     * {@link #UNSUPPORTED} will be returned.
+     * @hide
+     */
+    public static native long getRxBytes(String iface);
+
+
+    /**
      * Get the total number of packets sent through all network interfaces.
      *
      * @return the number of packets.  If the statistics are not supported by this device,
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index dfa36ce..0c84f11 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -130,6 +130,33 @@
             "/sys/class/net/ppp0/statistics/rx_bytes");
 }
 
+static jlong getData(JNIEnv* env, char *what, jstring interface) {
+    char filename[80];
+    jboolean isCopy;
+
+    const char *interfaceStr = env->GetStringUTFChars(interface, &isCopy);
+    snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s", interfaceStr, what);
+
+    return readNumber(filename);
+}
+
+static jlong getTxPackets(JNIEnv* env, jobject clazz, jstring interface) {
+    return getData(env, "tx_packets", interface);
+}
+
+static jlong getRxPackets(JNIEnv* env, jobject clazz, jstring interface) {
+    return getData(env, "rx_packets", interface);
+}
+
+static jlong getTxBytes(JNIEnv* env, jobject clazz, jstring interface) {
+    return getData(env, "tx_bytes", interface);
+}
+
+static jlong getRxBytes(JNIEnv* env, jobject clazz, jstring interface) {
+    return getData(env, "rx_bytes", interface);
+}
+
+
 // Total stats are read less often, so we're willing to put up
 // with listing the directory and concatenating filenames.
 
@@ -288,6 +315,10 @@
     {"getMobileRxPackets", "()J", (void*) getMobileRxPackets},
     {"getMobileTxBytes", "()J", (void*) getMobileTxBytes},
     {"getMobileRxBytes", "()J", (void*) getMobileRxBytes},
+    {"getTxPackets", "(Ljava/lang/String;)J", (void*) getTxPackets},
+    {"getRxPackets", "(Ljava/lang/String;)J", (void*) getRxPackets},
+    {"getTxBytes", "(Ljava/lang/String;)J", (void*) getTxBytes},
+    {"getRxBytes", "(Ljava/lang/String;)J", (void*) getRxBytes},
     {"getTotalTxPackets", "()J", (void*) getTotalTxPackets},
     {"getTotalRxPackets", "()J", (void*) getTotalRxPackets},
     {"getTotalTxBytes", "()J", (void*) getTotalTxBytes},
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 42868db..ef37b4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -33,6 +33,11 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.provider.Telephony;
@@ -50,6 +55,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.server.am.BatteryStatsService;
+import com.android.internal.util.AsyncChannel;
 
 import com.android.systemui.R;
 
@@ -82,6 +88,7 @@
 
     // wifi
     final WifiManager mWifiManager;
+    AsyncChannel mWifiChannel;
     boolean mWifiEnabled, mWifiConnected;
     int mWifiLevel;
     String mWifiSsid;
@@ -140,6 +147,14 @@
 
         // wifi
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        HandlerThread handlerThread = new HandlerThread("WifiServiceThread");
+        handlerThread.start();
+        Handler handler = new WifiHandler(handlerThread.getLooper());
+        mWifiChannel = new AsyncChannel();
+        Messenger wifiMessenger = mWifiManager.getMessenger();
+        if (wifiMessenger != null) {
+            mWifiChannel.connect(mContext, handler, wifiMessenger);
+        }
 
         // broadcasts
         IntentFilter filter = new IntentFilter();
@@ -584,6 +599,44 @@
 
     // ===== Wifi ===================================================================
 
+    class WifiHandler extends Handler {
+
+        WifiHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        mWifiChannel.sendMessage(Message.obtain(this,
+                                AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
+                    } else {
+                        Slog.e(TAG, "Failed to connect to wifi");
+                    }
+                    break;
+                case WifiManager.DATA_ACTIVITY_NOTIFICATION:
+                    int dataActivity = msg.arg1;
+                    /* TODO: update icons based on data activity */
+                    switch (dataActivity) {
+                        case WifiManager.DATA_ACTIVITY_IN:
+                            break;
+                        case WifiManager.DATA_ACTIVITY_OUT:
+                            break;
+                        case WifiManager.DATA_ACTIVITY_INOUT:
+                            break;
+                        case WifiManager.DATA_ACTIVITY_NONE:
+                            break;
+                    }
+                    break;
+                default:
+                    //Ignore
+                    break;
+            }
+        }
+    }
+
     private void updateWifiState(Intent intent) {
         final String action = intent.getAction();
         if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 56fae81..cc25e8d 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -42,14 +42,18 @@
 import android.net.DhcpInfo;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
+import android.net.NetworkInfo.DetailedState;
+import android.net.TrafficStats;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.Messenger;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -111,6 +115,20 @@
 
     private final IBatteryStats mBatteryStats;
 
+    private boolean mEnableTrafficStatsPoll = false;
+    private int mTrafficStatsPollToken = 0;
+    private long mTxPkts;
+    private long mRxPkts;
+    /* Tracks last reported data activity */
+    private int mDataActivity;
+    private String mInterfaceName;
+
+    /**
+     * Interval in milliseconds between polling for traffic
+     * statistics
+     */
+    private static final int POLL_TRAFFIC_STATS_INTERVAL_MSECS = 1000;
+
     /**
      * See {@link Settings.Secure#WIFI_IDLE_MS}. This is the default value if a
      * Settings.Secure value is not present. This timeout value is chosen as
@@ -123,6 +141,9 @@
     private static final String ACTION_DEVICE_IDLE =
             "com.android.server.WifiManager.action.DEVICE_IDLE";
 
+    private static final int CMD_ENABLE_TRAFFIC_STATS_POLL = 1;
+    private static final int CMD_TRAFFIC_STATS_POLL        = 2;
+
     private boolean mIsReceiverRegistered = false;
 
 
@@ -180,18 +201,20 @@
     /**
      * Asynchronous channel to WifiStateMachine
      */
-    private AsyncChannel mChannel;
+    private AsyncChannel mWifiStateMachineChannel;
 
     /**
-     * TODO: Possibly change WifiService into an AsyncService.
+     * Clients receiving asynchronous messages
      */
-    private class WifiServiceHandler extends Handler {
-        private AsyncChannel mWshChannel;
+    private List<AsyncChannel> mClients = new ArrayList<AsyncChannel>();
 
-        WifiServiceHandler(android.os.Looper looper, Context context) {
+    /**
+     * Handles client connections
+     */
+    private class AsyncServiceHandler extends Handler {
+
+        AsyncServiceHandler(android.os.Looper looper) {
             super(looper);
-            mWshChannel = new AsyncChannel();
-            mWshChannel.connect(context, this, mWifiStateMachine.getHandler());
         }
 
         @Override
@@ -199,11 +222,33 @@
             switch (msg.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
                     if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        mChannel = mWshChannel;
+                        Slog.d(TAG, "New client listening to asynchronous messages");
+                        mClients.add((AsyncChannel) msg.obj);
                     } else {
-                        Slog.d(TAG, "WifiServicehandler.handleMessage could not connect error=" +
-                                msg.arg1);
-                        mChannel = null;
+                        Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
+                    }
+                    break;
+                }
+                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
+                    AsyncChannel ac = new AsyncChannel();
+                    ac.connect(mContext, this, msg.replyTo);
+                    break;
+                }
+                case CMD_ENABLE_TRAFFIC_STATS_POLL: {
+                    mEnableTrafficStatsPoll = (msg.arg1 == 1);
+                    mTrafficStatsPollToken++;
+                    if (mEnableTrafficStatsPoll) {
+                        notifyOnDataActivity();
+                        sendMessageDelayed(Message.obtain(this, CMD_TRAFFIC_STATS_POLL,
+                                mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS);
+                    }
+                    break;
+                }
+                case CMD_TRAFFIC_STATS_POLL: {
+                    if (msg.arg1 == mTrafficStatsPollToken) {
+                        notifyOnDataActivity();
+                        sendMessageDelayed(Message.obtain(this, CMD_TRAFFIC_STATS_POLL,
+                                mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS);
                     }
                     break;
                 }
@@ -214,7 +259,40 @@
             }
         }
     }
-    WifiServiceHandler mHandler;
+    private AsyncServiceHandler mAsyncServiceHandler;
+
+    /**
+     * Handles interaction with WifiStateMachine
+     */
+    private class WifiStateMachineHandler extends Handler {
+        private AsyncChannel mWsmChannel;
+
+        WifiStateMachineHandler(android.os.Looper looper) {
+            super(looper);
+            mWsmChannel = new AsyncChannel();
+            mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
+                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        mWifiStateMachineChannel = mWsmChannel;
+                    } else {
+                        Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1);
+                        mWifiStateMachineChannel = null;
+                    }
+                    break;
+                }
+                default: {
+                    Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg);
+                    break;
+                }
+            }
+        }
+    }
+    WifiStateMachineHandler mWifiStateMachineHandler;
 
     /**
      * Temporary for computing UIDS that are responsible for starting WIFI.
@@ -224,7 +302,10 @@
 
     WifiService(Context context) {
         mContext = context;
-        mWifiStateMachine = new WifiStateMachine(mContext);
+
+        mInterfaceName =  SystemProperties.get("wifi.interface", "wlan0");
+
+        mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
         mWifiStateMachine.enableRssiPolling(true);
         mBatteryStats = BatteryStatsService.getService();
 
@@ -232,10 +313,6 @@
         Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
         mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
 
-        HandlerThread wifiThread = new HandlerThread("WifiService");
-        wifiThread.start();
-        mHandler = new WifiServiceHandler(wifiThread.getLooper(), context);
-
         mContext.registerReceiver(
                 new BroadcastReceiver() {
                     @Override
@@ -271,6 +348,7 @@
                             switch(mNetworkInfo.getDetailedState()) {
                                 case CONNECTED:
                                 case DISCONNECTED:
+                                    evaluateTrafficStatsPolling();
                                     resetNotification();
                                     break;
                             }
@@ -281,6 +359,11 @@
                     }
                 }, filter);
 
+        HandlerThread wifiThread = new HandlerThread("WifiService");
+        wifiThread.start();
+        mAsyncServiceHandler = new AsyncServiceHandler(wifiThread.getLooper());
+        mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
+
         // Setting is in seconds
         NOTIFICATION_REPEAT_DELAY_MS = Settings.Secure.getInt(context.getContentResolver(),
                 Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
@@ -337,10 +420,10 @@
      */
     public boolean pingSupplicant() {
         enforceAccessPermission();
-        if (mChannel != null) {
-            return mWifiStateMachine.syncPingSupplicant(mChannel);
+        if (mWifiStateMachineChannel != null) {
+            return mWifiStateMachine.syncPingSupplicant(mWifiStateMachineChannel);
         } else {
-            Slog.e(TAG, "mChannel is not initialized");
+            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
             return false;
         }
     }
@@ -550,10 +633,10 @@
      */
     public int addOrUpdateNetwork(WifiConfiguration config) {
         enforceChangePermission();
-        if (mChannel != null) {
-            return mWifiStateMachine.syncAddOrUpdateNetwork(mChannel, config);
+        if (mWifiStateMachineChannel != null) {
+            return mWifiStateMachine.syncAddOrUpdateNetwork(mWifiStateMachineChannel, config);
         } else {
-            Slog.e(TAG, "mChannel is not initialized");
+            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
             return -1;
         }
     }
@@ -566,10 +649,10 @@
      */
     public boolean removeNetwork(int netId) {
         enforceChangePermission();
-        if (mChannel != null) {
-            return mWifiStateMachine.syncRemoveNetwork(mChannel, netId);
+        if (mWifiStateMachineChannel != null) {
+            return mWifiStateMachine.syncRemoveNetwork(mWifiStateMachineChannel, netId);
         } else {
-            Slog.e(TAG, "mChannel is not initialized");
+            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
             return false;
         }
     }
@@ -583,10 +666,11 @@
      */
     public boolean enableNetwork(int netId, boolean disableOthers) {
         enforceChangePermission();
-        if (mChannel != null) {
-            return mWifiStateMachine.syncEnableNetwork(mChannel, netId, disableOthers);
+        if (mWifiStateMachineChannel != null) {
+            return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId,
+                    disableOthers);
         } else {
-            Slog.e(TAG, "mChannel is not initialized");
+            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
             return false;
         }
     }
@@ -599,10 +683,10 @@
      */
     public boolean disableNetwork(int netId) {
         enforceChangePermission();
-        if (mChannel != null) {
-            return mWifiStateMachine.syncDisableNetwork(mChannel, netId);
+        if (mWifiStateMachineChannel != null) {
+            return mWifiStateMachine.syncDisableNetwork(mWifiStateMachineChannel, netId);
         } else {
-            Slog.e(TAG, "mChannel is not initialized");
+            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
             return false;
         }
     }
@@ -639,10 +723,10 @@
     public boolean saveConfiguration() {
         boolean result = true;
         enforceChangePermission();
-        if (mChannel != null) {
-            return mWifiStateMachine.syncSaveConfig(mChannel);
+        if (mWifiStateMachineChannel != null) {
+            return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel);
         } else {
-            Slog.e(TAG, "mChannel is not initialized");
+            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
             return false;
         }
     }
@@ -776,14 +860,23 @@
 
     public WpsResult startWps(WpsConfiguration config) {
         enforceChangePermission();
-        if (mChannel != null) {
-            return mWifiStateMachine.startWps(mChannel, config);
+        if (mWifiStateMachineChannel != null) {
+            return mWifiStateMachine.startWps(mWifiStateMachineChannel, config);
         } else {
-            Slog.e(TAG, "mChannel is not initialized");
+            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
             return new WpsResult(WpsResult.Status.FAILURE);
         }
     }
 
+    /**
+     * Get a reference to handler. This is used by a client to establish
+     * an AsyncChannel communication with WifiService
+     */
+    public Messenger getMessenger() {
+        enforceAccessPermission();
+        return new Messenger(mAsyncServiceHandler);
+    }
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -805,6 +898,7 @@
                 // Once the screen is on, we are not keeping WIFI running
                 // because of any locks so clear that tracking immediately.
                 reportStartWorkSource();
+                evaluateTrafficStatsPolling();
                 mWifiStateMachine.enableRssiPolling(true);
                 mWifiStateMachine.enableAllNetworks();
                 updateWifiState();
@@ -813,6 +907,7 @@
                     Slog.d(TAG, "ACTION_SCREEN_OFF");
                 }
                 mScreenOff = true;
+                evaluateTrafficStatsPolling();
                 mWifiStateMachine.enableRssiPolling(false);
                 /*
                  * Set a timer to put Wi-Fi to sleep, but only if the screen is off
@@ -1416,6 +1511,48 @@
         }
     }
 
+    /**
+     * Evaluate if traffic stats polling is needed based on
+     * connection and screen on status
+     */
+    private void evaluateTrafficStatsPolling() {
+        Message msg;
+        if (mNetworkInfo.getDetailedState() == DetailedState.CONNECTED && !mScreenOff) {
+            msg = Message.obtain(mAsyncServiceHandler, CMD_ENABLE_TRAFFIC_STATS_POLL, 1, 0);
+        } else {
+            msg = Message.obtain(mAsyncServiceHandler, CMD_ENABLE_TRAFFIC_STATS_POLL, 0, 0);
+        }
+        msg.sendToTarget();
+    }
+
+    private void notifyOnDataActivity() {
+        long sent, received;
+        long preTxPkts = mTxPkts, preRxPkts = mRxPkts;
+        int dataActivity = WifiManager.DATA_ACTIVITY_NONE;
+
+        mTxPkts = TrafficStats.getTxPackets(mInterfaceName);
+        mRxPkts = TrafficStats.getRxPackets(mInterfaceName);
+
+        if (preTxPkts > 0 || preRxPkts > 0) {
+            sent = mTxPkts - preTxPkts;
+            received = mRxPkts - preRxPkts;
+            if (sent > 0) {
+                dataActivity |= WifiManager.DATA_ACTIVITY_OUT;
+            }
+            if (received > 0) {
+                dataActivity |= WifiManager.DATA_ACTIVITY_IN;
+            }
+
+            if (dataActivity != mDataActivity && !mScreenOff) {
+                mDataActivity = dataActivity;
+                for (AsyncChannel client : mClients) {
+                    client.sendMessage(WifiManager.DATA_ACTIVITY_NOTIFICATION, mDataActivity);
+                }
+            }
+        }
+    }
+
+
     private void checkAndSetNotification() {
         // If we shouldn't place a notification on available networks, then
         // don't bother doing any of the following
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 847577f..7a9276d 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -1,16 +1,16 @@
 /**
  * Copyright (c) 2008, The Android Open Source Project
  *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0 
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
@@ -23,6 +23,7 @@
 import android.net.wifi.ScanResult;
 import android.net.DhcpInfo;
 
+import android.os.Messenger;
 import android.os.WorkSource;
 
 /**
@@ -111,5 +112,7 @@
     void forgetNetwork(int networkId);
 
     WpsResult startWps(in WpsConfiguration config);
+
+    Messenger getMessenger();
 }
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4ac03a8..0807a24 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -24,6 +24,7 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.WorkSource;
+import android.os.Messenger;
 
 import java.util.List;
 
@@ -60,7 +61,7 @@
      * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
      * enabling, disabling, or unknown. One extra provides this state as an int.
      * Another extra provides the previous state, if available.
-     * 
+     *
      * @see #EXTRA_WIFI_STATE
      * @see #EXTRA_PREVIOUS_WIFI_STATE
      */
@@ -71,7 +72,7 @@
      * The lookup key for an int that indicates whether Wi-Fi is enabled,
      * disabled, enabling, disabling, or unknown.  Retrieve it with
      * {@link android.content.Intent#getIntExtra(String,int)}.
-     * 
+     *
      * @see #WIFI_STATE_DISABLED
      * @see #WIFI_STATE_DISABLING
      * @see #WIFI_STATE_ENABLED
@@ -81,22 +82,22 @@
     public static final String EXTRA_WIFI_STATE = "wifi_state";
     /**
      * The previous Wi-Fi state.
-     * 
+     *
      * @see #EXTRA_WIFI_STATE
      */
     public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
-    
+
     /**
      * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if
      * it finishes successfully.
-     * 
+     *
      * @see #WIFI_STATE_CHANGED_ACTION
      * @see #getWifiState()
      */
     public static final int WIFI_STATE_DISABLING = 0;
     /**
      * Wi-Fi is disabled.
-     * 
+     *
      * @see #WIFI_STATE_CHANGED_ACTION
      * @see #getWifiState()
      */
@@ -104,14 +105,14 @@
     /**
      * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if
      * it finishes successfully.
-     * 
+     *
      * @see #WIFI_STATE_CHANGED_ACTION
      * @see #getWifiState()
      */
     public static final int WIFI_STATE_ENABLING = 2;
     /**
      * Wi-Fi is enabled.
-     * 
+     *
      * @see #WIFI_STATE_CHANGED_ACTION
      * @see #getWifiState()
      */
@@ -119,7 +120,7 @@
     /**
      * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling
      * or disabling.
-     * 
+     *
      * @see #WIFI_STATE_CHANGED_ACTION
      * @see #getWifiState()
      */
@@ -418,6 +419,22 @@
      */
     public static final int WIFI_FREQUENCY_BAND_2GHZ = 2;
 
+    /** List of asyncronous notifications
+     * @hide
+     */
+    public static final int DATA_ACTIVITY_NOTIFICATION = 1;
+
+    //Lowest bit indicates data reception and the second lowest
+    //bit indicates data transmitted
+    /** @hide */
+    public static final int DATA_ACTIVITY_NONE         = 0x00;
+    /** @hide */
+    public static final int DATA_ACTIVITY_IN           = 0x01;
+    /** @hide */
+    public static final int DATA_ACTIVITY_OUT          = 0x02;
+    /** @hide */
+    public static final int DATA_ACTIVITY_INOUT        = 0x03;
+
     IWifiManager mService;
     Handler mHandler;
 
@@ -478,7 +495,7 @@
      * <p/>
      * The new network will be marked DISABLED by default. To enable it,
      * called {@link #enableNetwork}.
-     * 
+     *
      * @param config the set of variables that describe the configuration,
      *            contained in a {@link WifiConfiguration} object.
      * @return the ID of the newly created network description. This is used in
@@ -518,7 +535,7 @@
     /**
      * Internal method for doing the RPC that creates a new network description
      * or updates an existing one.
-     * 
+     *
      * @param config The possibly sparse object containing the variables that
      *         are to set or updated in the network description.
      * @return the ID of the network on success, {@code -1} on failure.
@@ -705,7 +722,7 @@
      * Note: It is possible for this method to change the network IDs of
      * existing networks. You should assume the network IDs can be different
      * after calling this method.
-     * 
+     *
      * @return {@code true} if the operation succeeded
      */
     public boolean saveConfiguration() {
@@ -816,20 +833,20 @@
             return WIFI_STATE_UNKNOWN;
         }
     }
-    
+
     /**
-     * Return whether Wi-Fi is enabled or disabled. 
+     * Return whether Wi-Fi is enabled or disabled.
      * @return {@code true} if Wi-Fi is enabled
      * @see #getWifiState()
      */
     public boolean isWifiEnabled() {
         return getWifiState() == WIFI_STATE_ENABLED;
     }
-    
+
     /**
      * Calculates the level of the signal. This should be used any time a signal
      * is being shown.
-     * 
+     *
      * @param rssi The power of the signal measured in RSSI.
      * @param numLevels The number of levels to consider in the calculated
      *            level.
@@ -847,10 +864,10 @@
             return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
         }
     }
-    
+
     /**
      * Compares two signal strengths.
-     * 
+     *
      * @param rssiA The power of the first signal measured in RSSI.
      * @param rssiB The power of the second signal measured in RSSI.
      * @return Returns <0 if the first signal is weaker than the second signal,
@@ -1115,9 +1132,24 @@
     }
 
     /**
+     * Get a reference to WifiService handler. This is used by a client to establish
+     * an AsyncChannel communication with WifiService
+     *
+     * @return Messenger pointing to the WifiService handler
+     * @hide
+     */
+    public Messenger getMessenger() {
+        try {
+            return mService.getMessenger();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
      * Allows an application to keep the Wi-Fi radio awake.
      * Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
-     * Acquiring a WifiLock will keep the radio on until the lock is released.  Multiple 
+     * Acquiring a WifiLock will keep the radio on until the lock is released.  Multiple
      * applications may hold WifiLocks, and the radio will only be allowed to turn off when no
      * WifiLocks are held in any application.
      *
@@ -1153,7 +1185,7 @@
          * Locks the Wi-Fi radio on until {@link #release} is called.
          *
          * If this WifiLock is reference-counted, each call to {@code acquire} will increment the
-         * reference count, and the radio will remain locked as long as the reference count is 
+         * reference count, and the radio will remain locked as long as the reference count is
          * above zero.
          *
          * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 26fae7f..fc42ab8 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -435,10 +435,11 @@
 
     private final IBatteryStats mBatteryStats;
 
-    public WifiStateMachine(Context context) {
+    public WifiStateMachine(Context context, String wlanInterface) {
         super(TAG);
 
         mContext = context;
+        mInterfaceName = wlanInterface;
 
         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
         mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
@@ -449,7 +450,6 @@
         mWifiMonitor = new WifiMonitor(this);
         mDhcpInfoInternal = new DhcpInfoInternal();
         mWifiInfo = new WifiInfo();
-        mInterfaceName = SystemProperties.get("wifi.interface", "tiwlan0");
         mSupplicantStateTracker = new SupplicantStateTracker(context, this, getHandler());
         mWpsStateMachine = new WpsStateMachine(context, this, getHandler());
         mLinkProperties = new LinkProperties();