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

Commit c607d1db authored by Antonio Cansado's avatar Antonio Cansado Committed by android-build-merger
Browse files

Merge "Implementation of data usage callbacks." into nyc-dev am: 12d7ea81

am: 7e098af6

* commit '7e098af6':
  Implementation of data usage callbacks.
parents e54310c7 7e098af6
Loading
Loading
Loading
Loading
+94 −5
Original line number Original line Diff line number Diff line
@@ -25,9 +25,15 @@ import android.net.ConnectivityManager;
import android.net.DataUsageRequest;
import android.net.DataUsageRequest;
import android.net.NetworkIdentity;
import android.net.NetworkIdentity;
import android.net.NetworkTemplate;
import android.net.NetworkTemplate;
import android.net.INetworkStatsService;
import android.os.Binder;
import android.os.Build;
import android.os.Build;
import android.os.Message;
import android.os.Messenger;
import android.os.Handler;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.Log;


/**
/**
@@ -75,16 +81,26 @@ import android.util.Log;
 * not included.
 * not included.
 */
 */
public class NetworkStatsManager {
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 Context mContext;
    private final INetworkStatsService mService;


    /**
    /**
     * {@hide}
     * {@hide}
     */
     */
    public NetworkStatsManager(Context context) {
    public NetworkStatsManager(Context context) {
        mContext = 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
     * 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
     * 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(policy, "DataUsagePolicy cannot be null");
        checkNotNull(callback, "DataUsageCallback 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.
     * @param callback The {@link DataUsageCallback} used when registering.
     */
     */
    public void unregisterDataUsageCallback(DataUsageCallback callback) {
    public void unregisterDataUsageCallback(DataUsageCallback callback) {
        checkNotNull(callback, "DataUsageCallback cannot be null");
        if (callback == null || callback.request == null

                || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
        // TODO: Implement stub.
            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;
        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 Original line Diff line number Diff line
@@ -31,6 +31,11 @@ import java.util.Objects;
 */
 */
public class DataUsageRequest implements Parcelable {
public class DataUsageRequest implements Parcelable {


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

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


package android.net;
package android.net;


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


/** {@hide} */
/** {@hide} */
interface INetworkStatsService {
interface INetworkStatsService {
@@ -57,4 +60,11 @@ interface INetworkStatsService {
    /** Advise persistance threshold; may be overridden internally. */
    /** Advise persistance threshold; may be overridden internally. */
    void advisePersistThreshold(long thresholdBytes);
    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 Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.net;
package com.android.server.net;


import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
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_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
import static android.net.TrafficStats.UID_TETHERING;


@@ -48,6 +49,7 @@ public final class NetworkStatsAccess {
    @IntDef({
    @IntDef({
            Level.DEFAULT,
            Level.DEFAULT,
            Level.USER,
            Level.USER,
            Level.DEVICESUMMARY,
            Level.DEVICE,
            Level.DEVICE,
    })
    })
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
@@ -147,6 +149,12 @@ public final class NetworkStatsAccess {
                // Device-level access - can access usage for any uid.
                // Device-level access - can access usage for any uid.
                return true;
                return true;
            case NetworkStatsAccess.Level.DEVICESUMMARY:
            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:
            case NetworkStatsAccess.Level.USER:
                // User-level access - can access usage for any app running in the same user, along
                // User-level access - can access usage for any app running in the same user, along
                // with some special uids (system, removed, or tethering).
                // with some special uids (system, removed, or tethering).
+25 −3
Original line number Original line Diff line number Diff line
@@ -135,7 +135,11 @@ public class NetworkStatsCollection implements FileRotator.Reader {
    }
    }


    public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
    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();
        IntArray uids = new IntArray();
        for (int i = 0; i < mStats.size(); i++) {
        for (int i = 0; i < mStats.size(); i++) {
            final Key key = mStats.keyAt(i);
            final Key key = mStats.keyAt(i);
@@ -169,7 +173,17 @@ public class NetworkStatsCollection implements FileRotator.Reader {
    public NetworkStatsHistory getHistory(
    public NetworkStatsHistory getHistory(
            NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end,
            NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end,
            @NetworkStatsAccess.Level int accessLevel) {
            @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)) {
        if (!NetworkStatsAccess.isAccessibleToUser(uid, callerUid, accessLevel)) {
            throw new SecurityException("Network stats history of uid " + uid
            throw new SecurityException("Network stats history of uid " + uid
                    + " is forbidden for caller " + callerUid);
                    + " is forbidden for caller " + callerUid);
@@ -198,6 +212,15 @@ public class NetworkStatsCollection implements FileRotator.Reader {
     */
     */
    public NetworkStats getSummary(NetworkTemplate template, long start, long end,
    public NetworkStats getSummary(NetworkTemplate template, long start, long end,
            @NetworkStatsAccess.Level int accessLevel) {
            @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 long now = System.currentTimeMillis();


        final NetworkStats stats = new NetworkStats(end - start, 24);
        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();
        final NetworkStats.Entry entry = new NetworkStats.Entry();
        NetworkStatsHistory.Entry historyEntry = null;
        NetworkStatsHistory.Entry historyEntry = null;


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