NetworkLogger.java revision a9ff206af26871695bfce54969428b8ad03e31e6
1/* 2 * Copyright (C) 2016 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.devicepolicy; 18 19import android.app.admin.ConnectEvent; 20import android.app.admin.DnsEvent; 21import android.app.admin.NetworkEvent; 22import android.content.pm.PackageManagerInternal; 23import android.net.IIpConnectivityMetrics; 24import android.net.INetdEventCallback; 25import android.os.Bundle; 26import android.os.Handler; 27import android.os.Message; 28import android.os.Process; 29import android.os.RemoteException; 30import android.util.Log; 31import android.util.Slog; 32 33import com.android.server.ServiceThread; 34 35import java.util.ArrayList; 36import java.util.List; 37 38/** 39 * A class for managing network logging. 40 * This class is not thread-safe, callers should synchronize access. 41 */ 42final class NetworkLogger { 43 44 private static final String TAG = NetworkLogger.class.getSimpleName(); 45 46 private final DevicePolicyManagerService mDpm; 47 private final PackageManagerInternal mPm; 48 49 private IIpConnectivityMetrics mIpConnectivityMetrics; 50 private ServiceThread mHandlerThread; 51 private NetworkLoggingHandler mNetworkLoggingHandler; 52 private boolean mIsLoggingEnabled; 53 54 private final INetdEventCallback mNetdEventCallback = new INetdEventCallback.Stub() { 55 @Override 56 public void onDnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount, 57 long timestamp, int uid) { 58 if (!mIsLoggingEnabled) { 59 return; 60 } 61 DnsEvent dnsEvent = new DnsEvent(hostname, ipAddresses, ipAddressesCount, 62 mPm.getNameForUid(uid), timestamp); 63 sendNetworkEvent(dnsEvent); 64 } 65 66 @Override 67 public void onConnectEvent(String ipAddr, int port, long timestamp, int uid) { 68 if (!mIsLoggingEnabled) { 69 return; 70 } 71 ConnectEvent connectEvent = new ConnectEvent(ipAddr, port, mPm.getNameForUid(uid), 72 timestamp); 73 sendNetworkEvent(connectEvent); 74 } 75 76 private void sendNetworkEvent(NetworkEvent event) { 77 Message msg = mNetworkLoggingHandler.obtainMessage( 78 NetworkLoggingHandler.LOG_NETWORK_EVENT_MSG); 79 Bundle bundle = new Bundle(); 80 bundle.putParcelable(NetworkLoggingHandler.NETWORK_EVENT_KEY, event); 81 msg.setData(bundle); 82 mNetworkLoggingHandler.sendMessage(msg); 83 } 84 }; 85 86 NetworkLogger(DevicePolicyManagerService dpm, PackageManagerInternal pm) { 87 mDpm = dpm; 88 mPm = pm; 89 } 90 91 private boolean checkIpConnectivityMetricsService() { 92 if (mIpConnectivityMetrics != null) { 93 return true; 94 } 95 final IIpConnectivityMetrics service = mDpm.mInjector.getIIpConnectivityMetrics(); 96 if (service == null) { 97 return false; 98 } 99 mIpConnectivityMetrics = service; 100 return true; 101 } 102 103 boolean startNetworkLogging() { 104 Log.d(TAG, "Starting network logging."); 105 if (!checkIpConnectivityMetricsService()) { 106 // the IIpConnectivityMetrics service should have been present at this point 107 Slog.wtf(TAG, "Failed to register callback with IIpConnectivityMetrics."); 108 return false; 109 } 110 try { 111 if (mIpConnectivityMetrics.registerNetdEventCallback(mNetdEventCallback)) { 112 mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, 113 /* allowIo */ false); 114 mHandlerThread.start(); 115 mNetworkLoggingHandler = new NetworkLoggingHandler(mHandlerThread.getLooper(), 116 mDpm); 117 mNetworkLoggingHandler.scheduleBatchFinalization( 118 NetworkLoggingHandler.BATCH_FINALIZATION_TIMEOUT_MS); 119 mIsLoggingEnabled = true; 120 return true; 121 } else { 122 return false; 123 } 124 } catch (RemoteException re) { 125 Slog.wtf(TAG, "Failed to make remote calls to register the callback", re); 126 return false; 127 } 128 } 129 130 boolean stopNetworkLogging() { 131 Log.d(TAG, "Stopping network logging"); 132 // stop the logging regardless of whether we fail to unregister listener 133 mIsLoggingEnabled = false; 134 try { 135 if (!checkIpConnectivityMetricsService()) { 136 // the IIpConnectivityMetrics service should have been present at this point 137 Slog.wtf(TAG, "Failed to unregister callback with IIpConnectivityMetrics."); 138 // logging is forcefully disabled even if unregistering fails 139 return true; 140 } 141 return mIpConnectivityMetrics.unregisterNetdEventCallback(); 142 } catch (RemoteException re) { 143 Slog.wtf(TAG, "Failed to make remote calls to unregister the callback", re); 144 } finally { 145 mHandlerThread.quitSafely(); 146 return true; 147 } 148 } 149 150 List<NetworkEvent> retrieveLogs(long batchToken) { 151 return mNetworkLoggingHandler.retrieveFullLogBatch(batchToken); 152 } 153} 154