Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 227bec49 authored by Irfan Sheriff's avatar Irfan Sheriff
Browse files

data activity reporting on wifi

Initial checkin, need icons to complete the feature

Bug: 3412258

Change-Id: I9a3ecc8159cc314d84707065dafe23d402409a84
parent 7cb0d07f
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -68,6 +68,43 @@ public class TrafficStats {
     */
    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.
     *
+31 −0
Original line number Diff line number Diff line
@@ -130,6 +130,33 @@ static jlong getMobileRxBytes(JNIEnv* env, jobject clazz) {
            "/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 @@ static JNINativeMethod gMethods[] = {
    {"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},
+53 −0
Original line number Diff line number Diff line
@@ -33,6 +33,11 @@ import android.net.wifi.WifiConfiguration;
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.IccCard;
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 @@ public class NetworkController extends BroadcastReceiver {

    // wifi
    final WifiManager mWifiManager;
    AsyncChannel mWifiChannel;
    boolean mWifiEnabled, mWifiConnected;
    int mWifiLevel;
    String mWifiSsid;
@@ -140,6 +147,14 @@ public class NetworkController extends BroadcastReceiver {

        // 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 @@ public class NetworkController extends BroadcastReceiver {

    // ===== 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)) {
+175 −38
Original line number Diff line number Diff line
@@ -42,14 +42,18 @@ import android.net.ConnectivityManager;
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 @@ public class WifiService extends IWifiManager.Stub {

    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 @@ public class WifiService extends IWifiManager.Stub {
    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 @@ public class WifiService extends IWifiManager.Stub {
    /**
     * 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 @@ public class WifiService extends IWifiManager.Stub {
            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 @@ public class WifiService extends IWifiManager.Stub {
            }
        }
    }
    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 @@ public class WifiService extends IWifiManager.Stub {

    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 @@ public class WifiService extends IWifiManager.Stub {
        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 @@ public class WifiService extends IWifiManager.Stub {
                            switch(mNetworkInfo.getDetailedState()) {
                                case CONNECTED:
                                case DISCONNECTED:
                                    evaluateTrafficStatsPolling();
                                    resetNotification();
                                    break;
                            }
@@ -281,6 +359,11 @@ public class WifiService extends IWifiManager.Stub {
                    }
                }, 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 class WifiService extends IWifiManager.Stub {
     */
    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 class WifiService extends IWifiManager.Stub {
     */
    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 class WifiService extends IWifiManager.Stub {
     */
    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 class WifiService extends IWifiManager.Stub {
     */
    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 class WifiService extends IWifiManager.Stub {
     */
    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 class WifiService extends IWifiManager.Stub {
    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 class WifiService extends IWifiManager.Stub {

    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 @@ public class WifiService extends IWifiManager.Stub {
                // 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 @@ public class WifiService extends IWifiManager.Stub {
                    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 @@ public class WifiService extends IWifiManager.Stub {
        }
    }

    /**
     * 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
+11 −8
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.net.wifi.WpsResult;
import android.net.wifi.ScanResult;
import android.net.DhcpInfo;

import android.os.Messenger;
import android.os.WorkSource;

/**
@@ -111,5 +112,7 @@ interface IWifiManager
    void forgetNetwork(int networkId);

    WpsResult startWps(in WpsConfiguration config);

    Messenger getMessenger();
}
Loading