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.permissioncontroller.permission.utils; 18 19 import android.content.pm.PackageInfo; 20 import android.util.ArrayMap; 21 import android.util.ArraySet; 22 import android.util.EventLog; 23 24 import com.android.permissioncontroller.permission.model.AppPermissionGroup; 25 import com.android.permissioncontroller.permission.model.Permission; 26 import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup; 27 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission; 28 29 import java.util.ArrayList; 30 import java.util.List; 31 32 public final class SafetyNetLogger { 33 34 // The log tag used by SafetyNet to pick entries from the event log. 35 private static final int SNET_NET_EVENT_LOG_TAG = 0x534e4554; 36 37 // Log tag for the result of permissions request. 38 private static final String PERMISSIONS_REQUESTED = "individual_permissions_requested"; 39 40 // Log tag for the result of permissions toggling. 41 private static final String PERMISSIONS_TOGGLED = "individual_permissions_toggled"; 42 SafetyNetLogger()43 private SafetyNetLogger() { 44 /* do nothing */ 45 } 46 47 /** 48 * Log that permission groups have been requested for the purpose of safety net. 49 * 50 * <p>The groups might refer to different permission groups and different apps. 51 * 52 * @param packageInfo The info about the package for which permissions were requested 53 * @param groups The permission groups which were requested 54 */ logPermissionsRequested(PackageInfo packageInfo, List<AppPermissionGroup> groups)55 public static void logPermissionsRequested(PackageInfo packageInfo, 56 List<AppPermissionGroup> groups) { 57 EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_REQUESTED, 58 packageInfo.applicationInfo.uid, buildChangedPermissionForPackageMessage( 59 packageInfo.packageName, groups)); 60 } 61 62 /** 63 * Log that permission groups have been requested for the purpose of safety net. 64 * 65 * <p>The groups might refer to different permission groups and different apps. 66 * 67 * @param packageName The name of the package for which permissions were requested 68 * @param uid The uid of the package 69 * @param groups The permission groups which were requested 70 */ logPermissionsRequested(String packageName, int uid, List<LightAppPermGroup> groups)71 public static void logPermissionsRequested(String packageName, int uid, 72 List<LightAppPermGroup> groups) { 73 EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_REQUESTED, uid, 74 buildChangedPermissionForPackageMessageNew(packageName, groups)); 75 } 76 77 /** 78 * Log that permission groups have been toggled for the purpose of safety net. 79 * 80 * <p>The groups might refer to different permission groups and different apps. 81 * 82 * @param groups The groups toggled 83 */ logPermissionsToggled(ArraySet<AppPermissionGroup> groups)84 public static void logPermissionsToggled(ArraySet<AppPermissionGroup> groups) { 85 ArrayMap<String, ArrayList<AppPermissionGroup>> groupsByPackage = new ArrayMap<>(); 86 87 int numGroups = groups.size(); 88 for (int i = 0; i < numGroups; i++) { 89 AppPermissionGroup group = groups.valueAt(i); 90 91 ArrayList<AppPermissionGroup> groupsForThisPackage = groupsByPackage.get( 92 group.getApp().packageName); 93 if (groupsForThisPackage == null) { 94 groupsForThisPackage = new ArrayList<>(); 95 groupsByPackage.put(group.getApp().packageName, groupsForThisPackage); 96 } 97 98 groupsForThisPackage.add(group); 99 if (group.getBackgroundPermissions() != null) { 100 groupsForThisPackage.add(group.getBackgroundPermissions()); 101 } 102 } 103 104 int numPackages = groupsByPackage.size(); 105 for (int i = 0; i < numPackages; i++) { 106 EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_TOGGLED, 107 android.os.Process.myUid(), buildChangedPermissionForPackageMessage( 108 groupsByPackage.keyAt(i), groupsByPackage.valueAt(i))); 109 } 110 } 111 112 /** 113 * Log that a permission group has been toggled for the purpose of safety net. 114 * 115 * @param group The group toggled. 116 */ logPermissionToggled(AppPermissionGroup group)117 public static void logPermissionToggled(AppPermissionGroup group) { 118 ArraySet groups = new ArraySet<AppPermissionGroup>(1); 119 groups.add(group); 120 logPermissionsToggled(groups); 121 } 122 123 /** 124 * Log that a permission group has been toggled for the purpose of safety net. 125 * 126 * @param group The group which was toggled. This group must represent the current state, not 127 * the old state 128 * @param logOnlyBackground Whether to log only background permissions, or foreground and 129 * background 130 */ logPermissionToggled(LightAppPermGroup group, boolean logOnlyBackground)131 public static void logPermissionToggled(LightAppPermGroup group, boolean logOnlyBackground) { 132 StringBuilder builder = new StringBuilder(); 133 buildChangedPermissionForGroup(group, logOnlyBackground, builder); 134 EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_TOGGLED, 135 android.os.Process.myUid(), builder.toString()); 136 } 137 138 /** 139 * Log that a permission group has been toggled for the purpose of safety net. Logs both 140 * background and foreground permissions. 141 * 142 * @param group The group which was toggled. This group must represent the current state, not 143 * the old state 144 */ logPermissionToggled(LightAppPermGroup group)145 public static void logPermissionToggled(LightAppPermGroup group) { 146 logPermissionToggled(group, false); 147 } 148 buildChangedPermissionForGroup(LightAppPermGroup group, boolean logOnlyBackground, StringBuilder builder)149 private static void buildChangedPermissionForGroup(LightAppPermGroup group, 150 boolean logOnlyBackground, StringBuilder builder) { 151 152 builder.append(group.getPackageInfo().getPackageName()).append(':'); 153 154 for (LightPermission permission: group.getPermissions().values()) { 155 if (logOnlyBackground 156 && !group.getBackgroundPermNames().contains(permission.getName())) { 157 continue; 158 } 159 160 if (builder.length() > 0) { 161 builder.append(';'); 162 } 163 164 builder.append(permission.getName()).append('|'); 165 builder.append(permission.isGrantedIncludingAppOp()).append('|'); 166 builder.append(permission.getFlags()); 167 } 168 } 169 buildChangedPermissionForGroup(AppPermissionGroup group, StringBuilder builder)170 private static void buildChangedPermissionForGroup(AppPermissionGroup group, 171 StringBuilder builder) { 172 int permissionCount = group.getPermissions().size(); 173 for (int permissionNum = 0; permissionNum < permissionCount; permissionNum++) { 174 Permission permission = group.getPermissions().get(permissionNum); 175 176 if (builder.length() > 0) { 177 builder.append(';'); 178 } 179 180 builder.append(permission.getName()).append('|'); 181 builder.append(permission.isGrantedIncludingAppOp()).append('|'); 182 builder.append(permission.getFlags()); 183 } 184 } 185 buildChangedPermissionForPackageMessageNew(String packageName, List<LightAppPermGroup> groups)186 private static String buildChangedPermissionForPackageMessageNew(String packageName, 187 List<LightAppPermGroup> groups) { 188 StringBuilder builder = new StringBuilder(); 189 190 builder.append(packageName).append(':'); 191 for (LightAppPermGroup group: groups) { 192 buildChangedPermissionForGroup(group, false, builder); 193 } 194 return builder.toString(); 195 } 196 buildChangedPermissionForPackageMessage(String packageName, List<AppPermissionGroup> groups)197 private static String buildChangedPermissionForPackageMessage(String packageName, 198 List<AppPermissionGroup> groups) { 199 StringBuilder builder = new StringBuilder(); 200 201 builder.append(packageName).append(':'); 202 203 int groupCount = groups.size(); 204 for (int groupNum = 0; groupNum < groupCount; groupNum++) { 205 AppPermissionGroup group = groups.get(groupNum); 206 207 buildChangedPermissionForGroup(group, builder); 208 if (group.getBackgroundPermissions() != null) { 209 buildChangedPermissionForGroup(group.getBackgroundPermissions(), builder); 210 } 211 } 212 213 return builder.toString(); 214 } 215 } 216