Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.server.net;
     18 
     19 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
     20 import static android.net.NetworkStats.UID_ALL;
     21 import static android.net.TrafficStats.UID_REMOVED;
     22 import static android.net.TrafficStats.UID_TETHERING;
     23 
     24 import android.Manifest;
     25 import android.annotation.IntDef;
     26 import android.app.AppOpsManager;
     27 import android.app.admin.DeviceAdminInfo;
     28 import android.app.admin.DevicePolicyManagerInternal;
     29 import android.content.Context;
     30 import android.content.pm.PackageManager;
     31 import android.os.UserHandle;
     32 import android.telephony.TelephonyManager;
     33 
     34 import com.android.server.LocalServices;
     35 
     36 import java.lang.annotation.Retention;
     37 import java.lang.annotation.RetentionPolicy;
     38 
     39 /** Utility methods for controlling access to network stats APIs. */
     40 public final class NetworkStatsAccess {
     41     private NetworkStatsAccess() {}
     42 
     43     /**
     44      * Represents an access level for the network usage history and statistics APIs.
     45      *
     46      * <p>Access levels are in increasing order; that is, it is reasonable to check access by
     47      * verifying that the caller's access level is at least the minimum required level.
     48      */
     49     @IntDef({
     50             Level.DEFAULT,
     51             Level.USER,
     52             Level.DEVICESUMMARY,
     53             Level.DEVICE,
     54     })
     55     @Retention(RetentionPolicy.SOURCE)
     56     public @interface Level {
     57         /**
     58          * Default, unprivileged access level.
     59          *
     60          * <p>Can only access usage for one's own UID.
     61          *
     62          * <p>Every app will have at least this access level.
     63          */
     64         int DEFAULT = 0;
     65 
     66         /**
     67          * Access level for apps which can access usage for any app running in the same user.
     68          *
     69          * <p>Granted to:
     70          * <ul>
     71          * <li>Profile owners.
     72          * </ul>
     73          */
     74         int USER = 1;
     75 
     76         /**
     77          * Access level for apps which can access usage summary of device. Device summary includes
     78          * usage by apps running in any profiles/users, however this access level does not
     79          * allow querying usage of individual apps running in other profiles/users.
     80          *
     81          * <p>Granted to:
     82          * <ul>
     83          * <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
     84          * so it is not necessarily sufficient to declare this in the manifest.
     85          * <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
     86          * </ul>
     87          */
     88         int DEVICESUMMARY = 2;
     89 
     90         /**
     91          * Access level for apps which can access usage for any app on the device, including apps
     92          * running on other users/profiles.
     93          *
     94          * <p>Granted to:
     95          * <ul>
     96          * <li>Device owners.
     97          * <li>Carrier-privileged applications.
     98          * <li>The system UID.
     99          * </ul>
    100          */
    101         int DEVICE = 3;
    102     }
    103 
    104     /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
    105     public static @NetworkStatsAccess.Level int checkAccessLevel(
    106             Context context, int callingUid, String callingPackage) {
    107         final DevicePolicyManagerInternal dpmi = LocalServices.getService(
    108                 DevicePolicyManagerInternal.class);
    109         final TelephonyManager tm = (TelephonyManager)
    110                 context.getSystemService(Context.TELEPHONY_SERVICE);
    111         boolean hasCarrierPrivileges = tm != null &&
    112                 tm.checkCarrierPrivilegesForPackage(callingPackage) ==
    113                         TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
    114         boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
    115                 DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
    116         if (hasCarrierPrivileges || isDeviceOwner
    117                 || UserHandle.getAppId(callingUid) == android.os.Process.SYSTEM_UID) {
    118             // Carrier-privileged apps and device owners, and the system can access data usage for
    119             // all apps on the device.
    120             return NetworkStatsAccess.Level.DEVICE;
    121         }
    122 
    123         boolean hasAppOpsPermission = hasAppOpsPermission(context, callingUid, callingPackage);
    124         if (hasAppOpsPermission || context.checkCallingOrSelfPermission(
    125                 READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) {
    126             return NetworkStatsAccess.Level.DEVICESUMMARY;
    127         }
    128 
    129         boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
    130                 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
    131         if (isProfileOwner) {
    132             // Apps with the AppOps permission, profile owners, and apps with the privileged
    133             // permission can access data usage for all apps in this user/profile.
    134             return NetworkStatsAccess.Level.USER;
    135         }
    136 
    137         // Everyone else gets default access (only to their own UID).
    138         return NetworkStatsAccess.Level.DEFAULT;
    139     }
    140 
    141     /**
    142      * Returns whether the given caller should be able to access the given UID when the caller has
    143      * the given {@link NetworkStatsAccess.Level}.
    144      */
    145     public static boolean isAccessibleToUser(int uid, int callerUid,
    146             @NetworkStatsAccess.Level int accessLevel) {
    147         switch (accessLevel) {
    148             case NetworkStatsAccess.Level.DEVICE:
    149                 // Device-level access - can access usage for any uid.
    150                 return true;
    151             case NetworkStatsAccess.Level.DEVICESUMMARY:
    152                 // Can access usage for any app running in the same user, along
    153                 // with some special uids (system, removed, or tethering) and
    154                 // anonymized uids
    155                 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
    156                         || uid == UID_TETHERING || uid == UID_ALL
    157                         || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
    158             case NetworkStatsAccess.Level.USER:
    159                 // User-level access - can access usage for any app running in the same user, along
    160                 // with some special uids (system, removed, or tethering).
    161                 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
    162                         || uid == UID_TETHERING
    163                         || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
    164             case NetworkStatsAccess.Level.DEFAULT:
    165             default:
    166                 // Default access level - can only access one's own usage.
    167                 return uid == callerUid;
    168         }
    169     }
    170 
    171     private static boolean hasAppOpsPermission(
    172             Context context, int callingUid, String callingPackage) {
    173         if (callingPackage != null) {
    174             AppOpsManager appOps = (AppOpsManager) context.getSystemService(
    175                     Context.APP_OPS_SERVICE);
    176 
    177             final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
    178                     callingUid, callingPackage);
    179             if (mode == AppOpsManager.MODE_DEFAULT) {
    180                 // The default behavior here is to check if PackageManager has given the app
    181                 // permission.
    182                 final int permissionCheck = context.checkCallingPermission(
    183                         Manifest.permission.PACKAGE_USAGE_STATS);
    184                 return permissionCheck == PackageManager.PERMISSION_GRANTED;
    185             }
    186             return (mode == AppOpsManager.MODE_ALLOWED);
    187         }
    188         return false;
    189     }
    190 }
    191