1 /* 2 * Copyright (C) 2017 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.backup.utils; 18 19 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS; 20 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME; 21 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_OPERATION_TYPE; 22 import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT; 23 import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS; 24 25 import static com.android.server.backup.BackupManagerService.DEBUG; 26 import static com.android.server.backup.BackupManagerService.TAG; 27 28 import android.annotation.Nullable; 29 import android.app.IBackupAgent; 30 import android.app.backup.BackupAnnotations.OperationType; 31 import android.app.backup.BackupManagerMonitor; 32 import android.app.backup.BackupRestoreEventLogger.DataTypeResult; 33 import android.app.backup.IBackupManagerMonitor; 34 import android.content.pm.PackageInfo; 35 import android.os.Bundle; 36 import android.os.RemoteException; 37 import android.util.Slog; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 import com.android.internal.infra.AndroidFuture; 41 42 import java.util.List; 43 import java.util.concurrent.TimeUnit; 44 import java.util.concurrent.TimeoutException; 45 46 /** 47 * Utility methods to log BackupManagerMonitor events. 48 */ 49 public class BackupManagerMonitorEventSender { 50 /** 51 * Timeout for how long we wait before we give up on getting logs from a {@link IBackupAgent}. 52 * We expect this to be very fast since the agent immediately returns whatever logs have been 53 * accumulated. The timeout adds a bit more security and ensures we don't hang the B&R waiting 54 * for non-essential logs. 55 */ 56 private static final int AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS = 500; 57 @Nullable private IBackupManagerMonitor mMonitor; 58 private final BackupManagerMonitorDumpsysUtils mBackupManagerMonitorDumpsysUtils; BackupManagerMonitorEventSender(@ullable IBackupManagerMonitor monitor)59 public BackupManagerMonitorEventSender(@Nullable IBackupManagerMonitor monitor) { 60 mMonitor = monitor; 61 mBackupManagerMonitorDumpsysUtils = new BackupManagerMonitorDumpsysUtils(); 62 } 63 64 @VisibleForTesting BackupManagerMonitorEventSender(@ullable IBackupManagerMonitor monitor, BackupManagerMonitorDumpsysUtils backupManagerMonitorDumpsysUtils)65 BackupManagerMonitorEventSender(@Nullable IBackupManagerMonitor monitor, 66 BackupManagerMonitorDumpsysUtils backupManagerMonitorDumpsysUtils) { 67 mMonitor = monitor; 68 mBackupManagerMonitorDumpsysUtils = backupManagerMonitorDumpsysUtils; 69 } 70 setMonitor(IBackupManagerMonitor monitor)71 public void setMonitor(IBackupManagerMonitor monitor) { 72 mMonitor = monitor; 73 } 74 getMonitor()75 public IBackupManagerMonitor getMonitor() { 76 return mMonitor; 77 } 78 79 /** 80 * Notifies monitor about the event. 81 * 82 * Calls {@link IBackupManagerMonitor#onEvent(Bundle)} with a bundle representing current event. 83 * 84 * @param id - event id. 85 * @param pkg - package event is related to. 86 * @param category - event category. 87 * @param extras - additional event data. 88 */ monitorEvent( int id, PackageInfo pkg, int category, Bundle extras)89 public void monitorEvent( 90 int id, 91 PackageInfo pkg, 92 int category, 93 Bundle extras) { 94 try { 95 Bundle bundle = new Bundle(); 96 bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID, id); 97 bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY, category); 98 if (pkg != null) { 99 bundle.putString(EXTRA_LOG_EVENT_PACKAGE_NAME, 100 pkg.packageName); 101 bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION, 102 pkg.versionCode); 103 bundle.putLong(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION, 104 pkg.getLongVersionCode()); 105 } 106 if (extras != null) { 107 bundle.putAll(extras); 108 if (extras.containsKey(EXTRA_LOG_OPERATION_TYPE) && 109 extras.getInt(EXTRA_LOG_OPERATION_TYPE) == OperationType.RESTORE){ 110 mBackupManagerMonitorDumpsysUtils 111 .parseBackupManagerMonitorRestoreEventForDumpsys(bundle); 112 } 113 } 114 115 if (mMonitor != null) { 116 mMonitor.onEvent(bundle); 117 } else { 118 if (DEBUG) { 119 Slog.w(TAG, "backup manager monitor is null unable to send event"); 120 } 121 } 122 } catch (RemoteException e) { 123 mMonitor = null; 124 if (DEBUG) { 125 Slog.w(TAG, "backup manager monitor went away"); 126 } 127 } 128 } 129 130 /** 131 * Extracts logging results from the provided {@code agent} and notifies the {@code monitor} 132 * about them. 133 * 134 * <p>Note that this method does two separate binder calls (one to the agent and one to the 135 * monitor). 136 * 137 * @param pkg - package the {@code agent} belongs to. 138 * @param agent - the {@link IBackupAgent} to retrieve logs from. 139 */ monitorAgentLoggingResults(PackageInfo pkg, IBackupAgent agent)140 public void monitorAgentLoggingResults(PackageInfo pkg, IBackupAgent agent) { 141 if (mMonitor == null) { 142 Slog.i(TAG, "backup manager monitor is null unable to send event"+pkg); 143 } 144 145 try { 146 AndroidFuture<List<DataTypeResult>> resultsFuture = 147 new AndroidFuture<>(); 148 AndroidFuture<Integer> operationTypeFuture = new AndroidFuture<>(); 149 agent.getLoggerResults(resultsFuture); 150 agent.getOperationType(operationTypeFuture); 151 sendAgentLoggingResults(pkg, 152 resultsFuture.get(AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS), 153 operationTypeFuture.get(AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS, 154 TimeUnit.MILLISECONDS)); 155 } catch (TimeoutException e) { 156 Slog.w(TAG, "Timeout while waiting to retrieve logging results from agent", e); 157 } catch (Exception e) { 158 Slog.w(TAG, "Failed to retrieve logging results from agent", e); 159 } 160 } 161 sendAgentLoggingResults(PackageInfo pkg, List<DataTypeResult> results, @OperationType int operationType)162 public void sendAgentLoggingResults(PackageInfo pkg, List<DataTypeResult> results, 163 @OperationType int operationType) { 164 Bundle loggerResultsBundle = new Bundle(); 165 loggerResultsBundle.putParcelableList( 166 EXTRA_LOG_AGENT_LOGGING_RESULTS, results); 167 loggerResultsBundle.putInt(EXTRA_LOG_OPERATION_TYPE, operationType); 168 monitorEvent( 169 LOG_EVENT_ID_AGENT_LOGGING_RESULTS, 170 pkg, 171 LOG_EVENT_CATEGORY_AGENT, 172 loggerResultsBundle); 173 } 174 175 /** 176 * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will 177 * be created. 178 * 179 * @param extras - bundle where to add key-value to, if null a new bundle will be created. 180 * @param key - key. 181 * @param value - value. 182 * @return extras if it was not null and new bundle otherwise. 183 */ putMonitoringExtra(Bundle extras, String key, String value)184 public static Bundle putMonitoringExtra(Bundle extras, String key, String value) { 185 if (extras == null) { 186 extras = new Bundle(); 187 } 188 extras.putString(key, value); 189 return extras; 190 } 191 192 /** 193 * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will 194 * be created. 195 * 196 * @param extras - bundle where to add key-value to, if null a new bundle will be created. 197 * @param key - key. 198 * @param value - value. 199 * @return extras if it was not null and new bundle otherwise. 200 */ putMonitoringExtra(Bundle extras, String key, long value)201 public static Bundle putMonitoringExtra(Bundle extras, String key, long value) { 202 if (extras == null) { 203 extras = new Bundle(); 204 } 205 extras.putLong(key, value); 206 return extras; 207 } 208 209 /** 210 * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will 211 * be created. 212 * 213 * @param extras - bundle where to add key-value to, if null a new bundle will be created. 214 * @param key - key. 215 * @param value - value. 216 * @return extras if it was not null and new bundle otherwise. 217 */ putMonitoringExtra(Bundle extras, String key, boolean value)218 public static Bundle putMonitoringExtra(Bundle extras, String key, boolean value) { 219 if (extras == null) { 220 extras = new Bundle(); 221 } 222 extras.putBoolean(key, value); 223 return extras; 224 } 225 226 /** 227 * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will 228 * be created. 229 * 230 * @param extras - bundle where to add key-value to, if null a new bundle will be created. 231 * @param key - key. 232 * @param value - value. 233 * @return extras if it was not null and new bundle otherwise. 234 */ putMonitoringExtra(Bundle extras, String key, int value)235 public static Bundle putMonitoringExtra(Bundle extras, String key, int value) { 236 if (extras == null) { 237 extras = new Bundle(); 238 } 239 extras.putInt(key, value); 240 return extras; 241 } 242 } 243