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