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

Commit 3ca6d6bb authored by Irfan Sheriff's avatar Irfan Sheriff Committed by Android (Google) Code Review
Browse files

Merge "data activity reporting on wifi"

parents 826fbd54 227bec49
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