blob: 98fe7707747c56bece774b6a4c76cc118b36e7fa [file] [log] [blame]
Jeff Davidson1efb1332015-12-09 18:04:50 -08001/*
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
17package com.android.server.net;
18
19import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
Antonio Cansadocd42acd2016-02-17 13:03:38 -080020import static android.net.NetworkStats.UID_ALL;
Jeff Davidson1efb1332015-12-09 18:04:50 -080021import static android.net.TrafficStats.UID_REMOVED;
22import static android.net.TrafficStats.UID_TETHERING;
23
24import android.Manifest;
25import android.annotation.IntDef;
26import android.app.AppOpsManager;
27import android.app.admin.DeviceAdminInfo;
28import android.app.admin.DevicePolicyManagerInternal;
29import android.content.Context;
30import android.content.pm.PackageManager;
31import android.os.UserHandle;
32import android.telephony.TelephonyManager;
33
34import com.android.server.LocalServices;
35
36import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
38
39/** Utility methods for controlling access to network stats APIs. */
40public 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,
Antonio Cansadocd42acd2016-02-17 13:03:38 -080052 Level.DEVICESUMMARY,
Jeff Davidson1efb1332015-12-09 18:04:50 -080053 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>
Jeff Davidson1efb1332015-12-09 18:04:50 -080071 * <li>Profile owners.
72 * </ul>
73 */
74 int USER = 1;
75
76 /**
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +000077 * 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 /**
Jeff Davidson1efb1332015-12-09 18:04:50 -080091 * 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 */
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +0000101 int DEVICE = 3;
Jeff Davidson1efb1332015-12-09 18:04:50 -0800102 }
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
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +0000123 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
Jeff Davidson1efb1332015-12-09 18:04:50 -0800129 boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
130 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +0000131 if (isProfileOwner) {
Jeff Davidson1efb1332015-12-09 18:04:50 -0800132 // 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;
Zoltan Szatmary-Ban3a8b3432016-01-21 10:44:37 +0000151 case NetworkStatsAccess.Level.DEVICESUMMARY:
Antonio Cansadocd42acd2016-02-17 13:03:38 -0800152 // 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);
Jeff Davidson1efb1332015-12-09 18:04:50 -0800158 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.checkOp(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}