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

Commit e5934548 authored by Junyu Lai's avatar Junyu Lai Committed by Automerger Merge Worker
Browse files

Merge "[MS41.1] Prepare for APIs for querying usage with template" am: 22c14816

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1937268

Change-Id: I36b6ca0261c998e57b48194bc14d465b8ada3193
parents d086e8ee 22c14816
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -556,7 +556,7 @@ public final class NetworkStats implements AutoCloseable {
    /**
     * Collects history results for uid and resets history enumeration index.
     */
    void startHistoryEnumeration(int uid, int tag, int state) {
    void startHistoryUidEnumeration(int uid, int tag, int state) {
        mHistory = null;
        try {
            mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
@@ -570,6 +570,20 @@ public final class NetworkStats implements AutoCloseable {
        mEnumerationIndex = 0;
    }

    /**
     * Collects history results for network and resets history enumeration index.
     */
    void startHistoryDeviceEnumeration() {
        try {
            mHistory = mSession.getHistoryIntervalForNetwork(
                    mTemplate, NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
        } catch (RemoteException e) {
            Log.w(TAG, e);
            mHistory = null;
        }
        mEnumerationIndex = 0;
    }

    /**
     * Starts uid enumeration for current user.
     * @throws RemoteException
+76 −9
Original line number Diff line number Diff line
@@ -433,6 +433,42 @@ public class NetworkStatsManager {
        return null; // To make the compiler happy.
    }

    /**
     * Query usage statistics details for networks matching a given {@link NetworkTemplate}.
     *
     * Result is not aggregated over time. This means buckets' start and
     * end timestamps will be between 'startTime' and 'endTime' parameters.
     * <p>Only includes buckets whose entire time period is included between
     * startTime and endTime. Doesn't interpolate or return partial buckets.
     * Since bucket length is in the order of hours, this
     * method cannot be used to measure data usage on a fine grained time scale.
     * This may take a long time, and apps should avoid calling this on their main thread.
     *
     * @param template Template used to match networks. See {@link NetworkTemplate}.
     * @param startTime Start of period, in milliseconds since the Unix epoch, see
     *                  {@link java.lang.System#currentTimeMillis}.
     * @param endTime End of period, in milliseconds since the Unix epoch, see
     *                {@link java.lang.System#currentTimeMillis}.
     * @return Statistics which is described above.
     * @hide
     */
    @NonNull
    // @SystemApi(client = MODULE_LIBRARIES)
    @WorkerThread
    public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template,
            long startTime, long endTime) {
        try {
            final NetworkStats result =
                    new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
            result.startHistoryDeviceEnumeration();
            return result;
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }

        return null; // To make the compiler happy.
    }

    /**
     * Query network usage statistics details for a given uid.
     * This may take a long time, and apps should avoid calling this on their main thread.
@@ -499,7 +535,8 @@ public class NetworkStatsManager {
     * @param endTime End of period. Defined in terms of "Unix time", see
     *            {@link java.lang.System#currentTimeMillis}.
     * @param uid UID of app
     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
     *            across all the tags.
     * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
     *            traffic from all states.
     * @return Statistics object or null if an error happened during statistics collection.
@@ -514,21 +551,51 @@ public class NetworkStatsManager {
        return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
    }

    /** @hide */
    public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
    /**
     * Query network usage statistics details for a given template, uid, tag, and state.
     *
     * Only usable for uids belonging to calling user. Result is not aggregated over time.
     * This means buckets' start and end timestamps are going to be between 'startTime' and
     * 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag
     * the same as the 'tag' parameter, and the state the same as the 'state' parameter.
     * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
     * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
     * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
     * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
     * interpolate across partial buckets. Since bucket length is in the order of hours, this
     * method cannot be used to measure data usage on a fine grained time scale.
     * This may take a long time, and apps should avoid calling this on their main thread.
     *
     * @param template Template used to match networks. See {@link NetworkTemplate}.
     * @param startTime Start of period, in milliseconds since the Unix epoch, see
     *                  {@link java.lang.System#currentTimeMillis}.
     * @param endTime End of period, in milliseconds since the Unix epoch, see
     *                {@link java.lang.System#currentTimeMillis}.
     * @param uid UID of app
     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
     *            across all the tags.
     * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
     *            traffic from all states.
     * @return Statistics which is described above.
     * @hide
     */
    @NonNull
    // @SystemApi(client = MODULE_LIBRARIES)
    @WorkerThread
    public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template,
            long startTime, long endTime, int uid, int tag, int state) throws SecurityException {

        NetworkStats result;
        try {
            result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
            result.startHistoryEnumeration(uid, tag, state);
            final NetworkStats result = new NetworkStats(
                    mContext, template, mFlags, startTime, endTime, mService);
            result.startHistoryUidEnumeration(uid, tag, state);
            return result;
        } catch (RemoteException e) {
            Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
                    + " state=" + state, e);
            return null;
            e.rethrowFromSystemServer();
        }

        return result;
        return null; // To make the compiler happy.
    }

    /**
+5 −0
Original line number Diff line number Diff line
@@ -32,6 +32,11 @@ interface INetworkStatsSession {
    /** Return historical network layer stats for traffic that matches template. */
    @UnsupportedAppUsage
    NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
    /**
     * Return historical network layer stats for traffic that matches template, start and end
     * timestamp.
     */
    NetworkStatsHistory getHistoryIntervalForNetwork(in NetworkTemplate template, int fields, long start, long end);

    /**
     * Return network layer usage summary per UID for traffic that matches template.
+57 −5
Original line number Diff line number Diff line
@@ -154,6 +154,7 @@ import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.BestClock;
import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.LocationPermissionChecker;
import com.android.net.module.util.NetworkStatsUtils;
import com.android.net.module.util.PermissionUtils;

@@ -365,6 +366,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
    @NonNull
    private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;

    @NonNull
    private final LocationPermissionChecker mLocationPermissionChecker;

    private static @NonNull File getDefaultSystemDir() {
        return new File(Environment.getDataDirectory(), "system");
    }
@@ -461,6 +465,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
        mContentResolver = mContext.getContentResolver();
        mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
                mNetworkStatsSubscriptionsMonitor);
        mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
    }

    /**
@@ -508,6 +513,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
                }
            };
        }

        /**
         * @see LocationPermissionChecker
         */
        public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
            return new LocationPermissionChecker(context);
        }
    }

    /**
@@ -773,6 +785,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
            @Override
            public NetworkStats getDeviceSummaryForNetwork(
                    NetworkTemplate template, long start, long end) {
                enforceTemplatePermissions(template, callingPackage);
                return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
                        mAccessLevel, mCallingUid);
            }
@@ -780,19 +793,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
            @Override
            public NetworkStats getSummaryForNetwork(
                    NetworkTemplate template, long start, long end) {
                enforceTemplatePermissions(template, callingPackage);
                return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
                        mAccessLevel, mCallingUid);
            }

            // TODO: Remove this after all callers are removed.
            @Override
            public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
                enforceTemplatePermissions(template, callingPackage);
                return internalGetHistoryForNetwork(template, restrictedFlags, fields,
                        mAccessLevel, mCallingUid);
                        mAccessLevel, mCallingUid, Long.MIN_VALUE, Long.MAX_VALUE);
            }

            @Override
            public NetworkStatsHistory getHistoryIntervalForNetwork(NetworkTemplate template,
                    int fields, long start, long end) {
                enforceTemplatePermissions(template, callingPackage);
                // TODO(b/200768422): Redact returned history if the template is location
                //  sensitive but the caller is not privileged.
                return internalGetHistoryForNetwork(template, restrictedFlags, fields,
                        mAccessLevel, mCallingUid, start, end);
            }

            @Override
            public NetworkStats getSummaryForAllUid(
                    NetworkTemplate template, long start, long end, boolean includeTags) {
                enforceTemplatePermissions(template, callingPackage);
                try {
                    final NetworkStats stats = getUidComplete()
                            .getSummary(template, start, end, mAccessLevel, mCallingUid);
@@ -810,6 +837,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
            @Override
            public NetworkStats getTaggedSummaryForAllUid(
                    NetworkTemplate template, long start, long end) {
                enforceTemplatePermissions(template, callingPackage);
                try {
                    final NetworkStats tagStats = getUidTagComplete()
                            .getSummary(template, start, end, mAccessLevel, mCallingUid);
@@ -822,6 +850,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
            @Override
            public NetworkStatsHistory getHistoryForUid(
                    NetworkTemplate template, int uid, int set, int tag, int fields) {
                enforceTemplatePermissions(template, callingPackage);
                // NOTE: We don't augment UID-level statistics
                if (tag == TAG_NONE) {
                    return getUidComplete().getHistory(template, null, uid, set, tag, fields,
@@ -836,6 +865,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
            public NetworkStatsHistory getHistoryIntervalForUid(
                    NetworkTemplate template, int uid, int set, int tag, int fields,
                    long start, long end) {
                enforceTemplatePermissions(template, callingPackage);
                // TODO(b/200768422): Redact returned history if the template is location
                //  sensitive but the caller is not privileged.
                // NOTE: We don't augment UID-level statistics
                if (tag == TAG_NONE) {
                    return getUidComplete().getHistory(template, null, uid, set, tag, fields,
@@ -857,6 +889,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
        };
    }

    private void enforceTemplatePermissions(@NonNull NetworkTemplate template,
            @NonNull String callingPackage) {
        // For a template with wifi network keys, it is possible for a malicious
        // client to track the user locations via querying data usage. Thus, enforce
        // fine location permission check.
        if (!template.getWifiNetworkKeys().isEmpty()) {
            final boolean canAccessFineLocation = mLocationPermissionChecker
                    .checkCallersLocationPermission(callingPackage,
                    null /* featureId */,
                            Binder.getCallingUid(),
                            false /* coarseForTargetSdkLessThanQ */,
                            null /* message */);
            if (!canAccessFineLocation) {
                throw new SecurityException("Access fine location is required when querying"
                        + " with wifi network keys, make sure the app has the necessary"
                        + "permissions and the location toggle is on.");
            }
        }
    }

    private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
        return NetworkStatsAccess.checkAccessLevel(
                mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
@@ -893,7 +945,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
        // We've been using pure XT stats long enough that we no longer need to
        // splice DEV and XT together.
        final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
                accessLevel, callingUid);
                accessLevel, callingUid, start, end);

        final long now = System.currentTimeMillis();
        final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
@@ -910,14 +962,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
     * appropriate.
     */
    private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
            int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
            int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid,
            long start, long end) {
        // We've been using pure XT stats long enough that we no longer need to
        // splice DEV and XT together.
        final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
        synchronized (mStatsLock) {
            return mXtStatsCached.getHistory(template, augmentPlan,
                    UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE,
                    accessLevel, callingUid);
                    UID_ALL, SET_ALL, TAG_NONE, fields, start, end, accessLevel, callingUid);
        }
    }