• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.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.DevicePolicyManager;
28 import android.content.Context;
29 import android.content.pm.PackageManager;
30 import android.os.Binder;
31 import android.os.Process;
32 import android.os.UserHandle;
33 import android.telephony.TelephonyManager;
34 
35 import com.android.net.module.util.PermissionUtils;
36 
37 import java.lang.annotation.Retention;
38 import java.lang.annotation.RetentionPolicy;
39 
40 /**
41  * Utility methods for controlling access to network stats APIs.
42  *
43  * @hide
44  */
45 public final class NetworkStatsAccess {
NetworkStatsAccess()46     private NetworkStatsAccess() {}
47 
48     /**
49      * Represents an access level for the network usage history and statistics APIs.
50      *
51      * <p>Access levels are in increasing order; that is, it is reasonable to check access by
52      * verifying that the caller's access level is at least the minimum required level.
53      */
54     @IntDef({
55             Level.DEFAULT,
56             Level.USER,
57             Level.DEVICESUMMARY,
58             Level.DEVICE,
59     })
60     @Retention(RetentionPolicy.SOURCE)
61     public @interface Level {
62         /**
63          * Default, unprivileged access level.
64          *
65          * <p>Can only access usage for one's own UID.
66          *
67          * <p>Every app will have at least this access level.
68          */
69         int DEFAULT = 0;
70 
71         /**
72          * Access level for apps which can access usage for any app running in the same user.
73          *
74          * <p>Granted to:
75          * <ul>
76          * <li>Profile owners.
77          * </ul>
78          */
79         int USER = 1;
80 
81         /**
82          * Access level for apps which can access usage summary of device. Device summary includes
83          * usage by apps running in any profiles/users, however this access level does not
84          * allow querying usage of individual apps running in other profiles/users.
85          *
86          * <p>Granted to:
87          * <ul>
88          * <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
89          * so it is not necessarily sufficient to declare this in the manifest.
90          * <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
91          * </ul>
92          */
93         int DEVICESUMMARY = 2;
94 
95         /**
96          * Access level for apps which can access usage for any app on the device, including apps
97          * running on other users/profiles.
98          *
99          * <p>Granted to:
100          * <ul>
101          * <li>Device owners.
102          * <li>Carrier-privileged applications.
103          * <li>The system UID.
104          * <li>NetworkStack application.
105          * </ul>
106          */
107         int DEVICE = 3;
108     }
109 
110     /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
checkAccessLevel( Context context, int callingPid, int callingUid, String callingPackage)111     public static @NetworkStatsAccess.Level int checkAccessLevel(
112             Context context, int callingPid, int callingUid, String callingPackage) {
113         final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class);
114         final TelephonyManager tm = (TelephonyManager)
115                 context.getSystemService(Context.TELEPHONY_SERVICE);
116         final boolean hasCarrierPrivileges;
117         final boolean isDeviceOwner;
118         long token = Binder.clearCallingIdentity();
119         try {
120             hasCarrierPrivileges = tm != null
121                     && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
122                             == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
123             isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
124         } finally {
125             Binder.restoreCallingIdentity(token);
126         }
127 
128         final int appId = UserHandle.getAppId(callingUid);
129 
130         final boolean isNetworkStack = PermissionUtils.checkAnyPermissionOf(
131                 context, callingPid, callingUid, android.Manifest.permission.NETWORK_STACK,
132                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
133 
134         if (hasCarrierPrivileges || isDeviceOwner
135                 || appId == Process.SYSTEM_UID || isNetworkStack) {
136             // Carrier-privileged apps and device owners, and the system (including the
137             // network stack) can access data usage for all apps on the device.
138             return NetworkStatsAccess.Level.DEVICE;
139         }
140 
141         final boolean hasAppOpsPermission =
142                 hasAppOpsPermission(context, callingUid, callingPackage);
143         if (hasAppOpsPermission || context.checkCallingOrSelfPermission(
144                 READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) {
145             return NetworkStatsAccess.Level.DEVICESUMMARY;
146         }
147 
148         final boolean isProfileOwner;
149         token = Binder.clearCallingIdentity();
150         try {
151             isProfileOwner = mDpm != null && mDpm.isProfileOwnerApp(callingPackage);
152         } finally {
153             Binder.restoreCallingIdentity(token);
154         }
155         if (isProfileOwner) {
156             // Apps with the AppOps permission, profile owners, and apps with the privileged
157             // permission can access data usage for all apps in this user/profile.
158             return NetworkStatsAccess.Level.USER;
159         }
160 
161         // Everyone else gets default access (only to their own UID).
162         return NetworkStatsAccess.Level.DEFAULT;
163     }
164 
165     /**
166      * Returns whether the given caller should be able to access the given UID when the caller has
167      * the given {@link NetworkStatsAccess.Level}.
168      */
isAccessibleToUser(int uid, int callerUid, @NetworkStatsAccess.Level int accessLevel)169     public static boolean isAccessibleToUser(int uid, int callerUid,
170             @NetworkStatsAccess.Level int accessLevel) {
171         final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
172         final int callerUserId = UserHandle.getUserHandleForUid(callerUid).getIdentifier();
173         switch (accessLevel) {
174             case NetworkStatsAccess.Level.DEVICE:
175                 // Device-level access - can access usage for any uid.
176                 return true;
177             case NetworkStatsAccess.Level.DEVICESUMMARY:
178                 // Can access usage for any app running in the same user, along
179                 // with some special uids (system, removed, or tethering) and
180                 // anonymized uids
181                 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
182                         || uid == UID_TETHERING || uid == UID_ALL
183                         || userId == callerUserId;
184             case NetworkStatsAccess.Level.USER:
185                 // User-level access - can access usage for any app running in the same user, along
186                 // with some special uids (system, removed, or tethering).
187                 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
188                         || uid == UID_TETHERING
189                         || userId == callerUserId;
190             case NetworkStatsAccess.Level.DEFAULT:
191             default:
192                 // Default access level - can only access one's own usage.
193                 return uid == callerUid;
194         }
195     }
196 
hasAppOpsPermission( Context context, int callingUid, String callingPackage)197     private static boolean hasAppOpsPermission(
198             Context context, int callingUid, String callingPackage) {
199         if (callingPackage != null) {
200             AppOpsManager appOps = (AppOpsManager) context.getSystemService(
201                     Context.APP_OPS_SERVICE);
202 
203             final int mode = appOps.noteOp(AppOpsManager.OPSTR_GET_USAGE_STATS,
204                     callingUid, callingPackage, null /* attributionTag */, null /* message */);
205             if (mode == AppOpsManager.MODE_DEFAULT) {
206                 // The default behavior here is to check if PackageManager has given the app
207                 // permission.
208                 final int permissionCheck = context.checkCallingPermission(
209                         Manifest.permission.PACKAGE_USAGE_STATS);
210                 return permissionCheck == PackageManager.PERMISSION_GRANTED;
211             }
212             return (mode == AppOpsManager.MODE_ALLOWED);
213         }
214         return false;
215     }
216 }
217