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

Commit 12d7ea81 authored by Antonio Cansado's avatar Antonio Cansado Committed by Android (Google) Code Review
Browse files

Merge "Implementation of data usage callbacks." into nyc-dev

parents 003ee198 cd42acd9
Loading
Loading
Loading
Loading
+94 −5
Original line number Diff line number Diff line
@@ -25,9 +25,15 @@ import android.net.ConnectivityManager;
import android.net.DataUsageRequest;
import android.net.NetworkIdentity;
import android.net.NetworkTemplate;
import android.net.INetworkStatsService;
import android.os.Binder;
import android.os.Build;
import android.os.Message;
import android.os.Messenger;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

/**
@@ -75,16 +81,26 @@ import android.util.Log;
 * not included.
 */
public class NetworkStatsManager {
    private final static String TAG = "NetworkStatsManager";
    private static final String TAG = "NetworkStatsManager";
    private static final boolean DBG = false;

    /** @hide */
    public static final int CALLBACK_LIMIT_REACHED = 0;
    /** @hide */
    public static final int CALLBACK_RELEASED = 1;

    private final Context mContext;
    private final INetworkStatsService mService;

    /**
     * {@hide}
     */
    public NetworkStatsManager(Context context) {
        mContext = context;
        mService = INetworkStatsService.Stub.asInterface(
                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
    }

    /**
     * Query network usage statistics summaries. Result is summarised data usage for the whole
     * device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This
@@ -322,7 +338,40 @@ public class NetworkStatsManager {
        checkNotNull(policy, "DataUsagePolicy cannot be null");
        checkNotNull(callback, "DataUsageCallback cannot be null");

        // TODO: Implement stub.
        final Looper looper;
        if (handler == null) {
            looper = Looper.myLooper();
        } else {
            looper = handler.getLooper();
        }

        if (DBG) Log.d(TAG, "registerDataUsageCallback called with " + policy);

        NetworkTemplate[] templates;
        if (policy.subscriberIds == null || policy.subscriberIds.length == 0) {
            templates = new NetworkTemplate[1];
            templates[0] = createTemplate(policy.networkType, null /* subscriberId */);
        } else {
            templates = new NetworkTemplate[policy.subscriberIds.length];
            for (int i = 0; i < policy.subscriberIds.length; i++) {
                templates[i] = createTemplate(policy.networkType, policy.subscriberIds[i]);
            }
        }
        DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
                templates, policy.uids, policy.thresholdInBytes);
        try {
            CallbackHandler callbackHandler = new CallbackHandler(looper, callback);
            callback.request = mService.registerDataUsageCallback(
                    mContext.getOpPackageName(), request, new Messenger(callbackHandler),
                    new Binder());
            if (DBG) Log.d(TAG, "registerDataUsageCallback returned " + callback.request);

            if (callback.request == null) {
                Log.e(TAG, "Request from callback is null; should not happen");
            }
        } catch (RemoteException e) {
            if (DBG) Log.d(TAG, "Remote exception when registering callback");
        }
    }

    /**
@@ -331,9 +380,15 @@ public class NetworkStatsManager {
     * @param callback The {@link DataUsageCallback} used when registering.
     */
    public void unregisterDataUsageCallback(DataUsageCallback callback) {
        checkNotNull(callback, "DataUsageCallback cannot be null");

        // TODO: Implement stub.
        if (callback == null || callback.request == null
                || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
            throw new IllegalArgumentException("Invalid DataUsageCallback");
        }
        try {
            mService.unregisterDataUsageRequest(callback.request);
        } catch (RemoteException e) {
            if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
        }
    }

    /**
@@ -366,4 +421,38 @@ public class NetworkStatsManager {
        }
        return template;
    }

    private static class CallbackHandler extends Handler {
        private DataUsageCallback mCallback;
        CallbackHandler(Looper looper, DataUsageCallback callback) {
            super(looper);
            mCallback = callback;
        }

        @Override
        public void handleMessage(Message message) {
            DataUsageRequest request =
                    (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);

            switch (message.what) {
                case CALLBACK_LIMIT_REACHED: {
                    if (mCallback != null) {
                        mCallback.onLimitReached();
                    } else {
                        Log.e(TAG, "limit reached with released callback for " + request);
                    }
                    break;
                }
                case CALLBACK_RELEASED: {
                    if (DBG) Log.d(TAG, "callback released for " + request);
                    mCallback = null;
                    break;
                }
            }
        }

        private static Object getObject(Message msg, String key) {
            return msg.getData().getParcelable(key);
        }
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -31,6 +31,11 @@ import java.util.Objects;
 */
public class DataUsageRequest implements Parcelable {

    /**
     * @hide
     */
    public static final String PARCELABLE_KEY = "DataUsageRequest";

    /**
     * @hide
     */
+10 −0
Original line number Diff line number Diff line
@@ -16,10 +16,13 @@

package android.net;

import android.net.DataUsageRequest;
import android.net.INetworkStatsSession;
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.IBinder;
import android.os.Messenger;

/** {@hide} */
interface INetworkStatsService {
@@ -57,4 +60,11 @@ interface INetworkStatsService {
    /** Advise persistance threshold; may be overridden internally. */
    void advisePersistThreshold(long thresholdBytes);

    /** Registers a callback on data usage. */
    DataUsageRequest registerDataUsageCallback(String callingPackage,
            in DataUsageRequest request, in Messenger messenger, in IBinder binder);

    /** Unregisters a callback on data usage. */
    void unregisterDataUsageRequest(in DataUsageRequest request);

}
+8 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.net;

import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;

@@ -48,6 +49,7 @@ public final class NetworkStatsAccess {
    @IntDef({
            Level.DEFAULT,
            Level.USER,
            Level.DEVICESUMMARY,
            Level.DEVICE,
    })
    @Retention(RetentionPolicy.SOURCE)
@@ -147,6 +149,12 @@ public final class NetworkStatsAccess {
                // Device-level access - can access usage for any uid.
                return true;
            case NetworkStatsAccess.Level.DEVICESUMMARY:
                // Can access usage for any app running in the same user, along
                // with some special uids (system, removed, or tethering) and
                // anonymized uids
                return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
                        || uid == UID_TETHERING || uid == UID_ALL
                        || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
            case NetworkStatsAccess.Level.USER:
                // User-level access - can access usage for any app running in the same user, along
                // with some special uids (system, removed, or tethering).
+25 −3
Original line number Diff line number Diff line
@@ -135,7 +135,11 @@ public class NetworkStatsCollection implements FileRotator.Reader {
    }

    public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
        final int callerUid = Binder.getCallingUid();
        return getRelevantUids(accessLevel, Binder.getCallingUid());
    }

    public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
                final int callerUid) {
        IntArray uids = new IntArray();
        for (int i = 0; i < mStats.size(); i++) {
            final Key key = mStats.keyAt(i);
@@ -169,7 +173,17 @@ public class NetworkStatsCollection implements FileRotator.Reader {
    public NetworkStatsHistory getHistory(
            NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end,
            @NetworkStatsAccess.Level int accessLevel) {
        final int callerUid = Binder.getCallingUid();
        return getHistory(template, uid, set, tag, fields, start, end, accessLevel,
                Binder.getCallingUid());
    }

    /**
     * Combine all {@link NetworkStatsHistory} in this collection which match
     * the requested parameters.
     */
    public NetworkStatsHistory getHistory(
            NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end,
            @NetworkStatsAccess.Level int accessLevel, int callerUid) {
        if (!NetworkStatsAccess.isAccessibleToUser(uid, callerUid, accessLevel)) {
            throw new SecurityException("Network stats history of uid " + uid
                    + " is forbidden for caller " + callerUid);
@@ -198,6 +212,15 @@ public class NetworkStatsCollection implements FileRotator.Reader {
     */
    public NetworkStats getSummary(NetworkTemplate template, long start, long end,
            @NetworkStatsAccess.Level int accessLevel) {
        return getSummary(template, start, end, accessLevel, Binder.getCallingUid());
    }

    /**
     * Summarize all {@link NetworkStatsHistory} in this collection which match
     * the requested parameters.
     */
    public NetworkStats getSummary(NetworkTemplate template, long start, long end,
            @NetworkStatsAccess.Level int accessLevel, int callerUid) {
        final long now = System.currentTimeMillis();

        final NetworkStats stats = new NetworkStats(end - start, 24);
@@ -207,7 +230,6 @@ public class NetworkStatsCollection implements FileRotator.Reader {
        final NetworkStats.Entry entry = new NetworkStats.Entry();
        NetworkStatsHistory.Entry historyEntry = null;

        final int callerUid = Binder.getCallingUid();
        for (int i = 0; i < mStats.size(); i++) {
            final Key key = mStats.keyAt(i);
            if (templateMatches(template, key.ident)
Loading