Loading apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java +73 −86 Original line number Original line Diff line number Diff line Loading @@ -54,11 +54,11 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.IOException; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.List; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** /** * Helper service for statsd (the native stats management service in cmds/statsd/). * Helper service for statsd (the native stats management service in cmds/statsd/). Loading Loading @@ -112,17 +112,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private final HashMap<Long, String> mDeletedFiles = new HashMap<>(); private final HashMap<Long, String> mDeletedFiles = new HashMap<>(); private final CompanionHandler mHandler; private final CompanionHandler mHandler; // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle. This // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle. // and the flag mSentBootComplete below is used for synchronization to ensure that the boot private AtomicBoolean mBootCompleted = new AtomicBoolean(false); // complete signal is only ever sent once to statsd. Two signals are needed because // #sayHiToStatsd can be called from both statsd and #onBootPhase // PHASE_THIRD_PARTY_APPS_CAN_START. @GuardedBy("sStatsdLock") private boolean mBootCompleted = false; // Flag that is set when IStatsd#bootCompleted is called. This flag ensures that boot complete // signal is only ever sent once. @GuardedBy("sStatsdLock") private boolean mSentBootComplete = false; public StatsCompanionService(Context context) { public StatsCompanionService(Context context) { super(); super(); Loading Loading @@ -607,27 +598,35 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // Statsd related code // Statsd related code /** /** * Fetches the statsd IBinder service. This is a blocking call. * Fetches the statsd IBinder service. This is a blocking call that always refetches statsd * instead of returning the cached sStatsd. * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use * the cached sStatsd via {@link #getStatsdNonblocking()}. * the cached sStatsd via {@link #getStatsdNonblocking()}. */ */ private IStatsd fetchStatsdService(StatsdDeathRecipient deathRecipient) { private IStatsd fetchStatsdServiceLocked() { synchronized (sStatsdLock) { if (sStatsd == null) { sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer .getStatsServiceManager() .getStatsServiceManager() .getStatsdServiceRegisterer() .getStatsdServiceRegisterer() .get()); .get()); if (sStatsd != null) { return sStatsd; } private void registerStatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) { StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(statsd, receivers); try { try { sStatsd.asBinder().linkToDeath(deathRecipient, /* flags */ 0); statsd.asBinder().linkToDeath(deathRecipient, /*flags=*/0); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed"); Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed"); statsdNotReadyLocked(); // Statsd has already died. Unregister receivers ourselves. for (BroadcastReceiver receiver : receivers) { mContext.unregisterReceiver(receiver); } } synchronized (sStatsdLock) { if (statsd == sStatsd) { statsdNotReadyLocked(); } } } } return sStatsd; } } } } Loading @@ -648,22 +647,23 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { * statsd. * statsd. */ */ private void sayHiToStatsd() { private void sayHiToStatsd() { if (getStatsdNonblocking() != null) { IStatsd statsd; Log.e(TAG, "Trying to fetch statsd, but it was already fetched", synchronized (sStatsdLock) { new IllegalStateException( if (sStatsd != null && sStatsd.asBinder().isBinderAlive()) { "sStatsd is not null when being fetched")); Log.e(TAG, "statsd has already been fetched before", new IllegalStateException("IStatsd object should be null or dead")); return; return; } } StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(); statsd = fetchStatsdServiceLocked(); IStatsd statsd = fetchStatsdService(deathRecipient); } if (statsd == null) { if (statsd == null) { Log.i(TAG, Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive."); "Could not yet find statsd to tell it that StatsCompanion is " + "alive."); return; return; } } mStatsManagerService.statsdReady(statsd); if (DEBUG) Log.d(TAG, "Saying hi to statsd"); if (DEBUG) Log.d(TAG, "Saying hi to statsd"); mStatsManagerService.statsdReady(statsd); try { try { statsd.statsCompanionReady(); statsd.statsCompanionReady(); Loading @@ -682,8 +682,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null); mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null); // Setup receiver for user initialize (which happens once for a new user) // Setup receiver for user initialize (which happens once for a new user) // and // and if a user is removed. // if a user is removed. filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_REMOVED); mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null); mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null); Loading @@ -691,27 +690,20 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // Setup receiver for device reboots or shutdowns. // Setup receiver for device reboots or shutdowns. filter = new IntentFilter(Intent.ACTION_REBOOT); filter = new IntentFilter(Intent.ACTION_REBOOT); filter.addAction(Intent.ACTION_SHUTDOWN); filter.addAction(Intent.ACTION_SHUTDOWN); mContext.registerReceiverForAllUsers( mContext.registerReceiverForAllUsers(shutdownEventReceiver, filter, null, null); shutdownEventReceiver, filter, null, null); // Only add the receivers if the registration is successful. // Register death recipient. deathRecipient.addRegisteredBroadcastReceivers( List<BroadcastReceiver> broadcastReceivers = List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver)); List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver); registerStatsdDeathRecipient(statsd, broadcastReceivers); // Used so we can call statsd.bootComplete() outside of the lock. // Tell statsd that boot has completed. The signal may have already been sent, but since boolean shouldSendBootComplete = false; // the signal-receiving function is idempotent, that's ok. synchronized (sStatsdLock) { if (mBootCompleted.get()) { if (mBootCompleted && !mSentBootComplete) { mSentBootComplete = true; shouldSendBootComplete = true; } } if (shouldSendBootComplete) { statsd.bootCompleted(); statsd.bootCompleted(); } } // Pull the latest state of UID->app name, version mapping when // Pull the latest state of UID->app name, version mapping when statsd starts. // statsd starts. informAllUids(mContext); informAllUids(mContext); Log.i(TAG, "Told statsd that StatsCompanionService is alive."); Log.i(TAG, "Told statsd that StatsCompanionService is alive."); Loading @@ -722,18 +714,16 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private class StatsdDeathRecipient implements IBinder.DeathRecipient { private class StatsdDeathRecipient implements IBinder.DeathRecipient { private List<BroadcastReceiver> mReceiversToUnregister; private final IStatsd mStatsd; private final List<BroadcastReceiver> mReceiversToUnregister; StatsdDeathRecipient() { mReceiversToUnregister = new ArrayList<>(); } public void addRegisteredBroadcastReceivers(List<BroadcastReceiver> receivers) { StatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) { synchronized (sStatsdLock) { mStatsd = statsd; mReceiversToUnregister.addAll(receivers); mReceiversToUnregister = receivers; } } } // It is possible for binderDied to be called after a restarted statsd calls statsdReady, // but that's alright because the code does not assume an ordering of the two calls. @Override @Override public void binderDied() { public void binderDied() { Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); Loading Loading @@ -762,13 +752,19 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } } } } } // We only unregister in binder death becaseu receivers can only be unregistered // once, or an IllegalArgumentException is thrown. // Unregister receivers on death because receivers can only be unregistered once. // Otherwise, an IllegalArgumentException is thrown. for (BroadcastReceiver receiver: mReceiversToUnregister) { for (BroadcastReceiver receiver: mReceiversToUnregister) { mContext.unregisterReceiver(receiver); mContext.unregisterReceiver(receiver); } } // It's possible for statsd to have restarted and called statsdReady, causing a new // sStatsd binder object to be fetched, before the binderDied callback runs. Only // call #statsdNotReadyLocked if that hasn't happened yet. if (mStatsd == sStatsd) { statsdNotReadyLocked(); statsdNotReadyLocked(); mSentBootComplete = false; } } } } } } } Loading @@ -779,20 +775,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } void bootCompleted() { void bootCompleted() { mBootCompleted.set(true); IStatsd statsd = getStatsdNonblocking(); IStatsd statsd = getStatsdNonblocking(); synchronized (sStatsdLock) { mBootCompleted = true; if (mSentBootComplete) { // do not send a boot complete a second time. return; } if (statsd == null) { if (statsd == null) { // Statsd is not yet ready. // Statsd is not yet ready. // Delay the boot completed ping to {@link #sayHiToStatsd()} // Delay the boot completed ping to {@link #sayHiToStatsd()} return; return; } } mSentBootComplete = true; } try { try { statsd.bootCompleted(); statsd.bootCompleted(); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -808,8 +797,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } synchronized (sStatsdLock) { synchronized (sStatsdLock) { writer.println( writer.println("Number of configuration files deleted: " + mDeletedFiles.size()); "Number of configuration files deleted: " + mDeletedFiles.size()); if (mDeletedFiles.size() > 0) { if (mDeletedFiles.size() > 0) { writer.println(" timestamp, deleted file name"); writer.println(" timestamp, deleted file name"); } } Loading @@ -817,8 +805,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime(); SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime(); for (Long elapsedMillis : mDeletedFiles.keySet()) { for (Long elapsedMillis : mDeletedFiles.keySet()) { long deletionMillis = lastBootMillis + elapsedMillis; long deletionMillis = lastBootMillis + elapsedMillis; writer.println( writer.println(" " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis)); " " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis)); } } } } } } Loading cmds/statsd/src/StatsService.cpp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -343,9 +343,11 @@ status_t StatsService::handleShellCommand(int in, int out, int err, const char** if (!utf8Args[0].compare(String8("print-logs"))) { if (!utf8Args[0].compare(String8("print-logs"))) { return cmd_print_logs(out, utf8Args); return cmd_print_logs(out, utf8Args); } } if (!utf8Args[0].compare(String8("send-active-configs"))) { if (!utf8Args[0].compare(String8("send-active-configs"))) { return cmd_trigger_active_config_broadcast(out, utf8Args); return cmd_trigger_active_config_broadcast(out, utf8Args); } } if (!utf8Args[0].compare(String8("data-subscribe"))) { if (!utf8Args[0].compare(String8("data-subscribe"))) { { { std::lock_guard<std::mutex> lock(mShellSubscriberMutex); std::lock_guard<std::mutex> lock(mShellSubscriberMutex); Loading Loading
apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java +73 −86 Original line number Original line Diff line number Diff line Loading @@ -54,11 +54,11 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.IOException; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.List; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** /** * Helper service for statsd (the native stats management service in cmds/statsd/). * Helper service for statsd (the native stats management service in cmds/statsd/). Loading Loading @@ -112,17 +112,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private final HashMap<Long, String> mDeletedFiles = new HashMap<>(); private final HashMap<Long, String> mDeletedFiles = new HashMap<>(); private final CompanionHandler mHandler; private final CompanionHandler mHandler; // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle. This // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle. // and the flag mSentBootComplete below is used for synchronization to ensure that the boot private AtomicBoolean mBootCompleted = new AtomicBoolean(false); // complete signal is only ever sent once to statsd. Two signals are needed because // #sayHiToStatsd can be called from both statsd and #onBootPhase // PHASE_THIRD_PARTY_APPS_CAN_START. @GuardedBy("sStatsdLock") private boolean mBootCompleted = false; // Flag that is set when IStatsd#bootCompleted is called. This flag ensures that boot complete // signal is only ever sent once. @GuardedBy("sStatsdLock") private boolean mSentBootComplete = false; public StatsCompanionService(Context context) { public StatsCompanionService(Context context) { super(); super(); Loading Loading @@ -607,27 +598,35 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // Statsd related code // Statsd related code /** /** * Fetches the statsd IBinder service. This is a blocking call. * Fetches the statsd IBinder service. This is a blocking call that always refetches statsd * instead of returning the cached sStatsd. * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use * Note: This should only be called from {@link #sayHiToStatsd()}. All other clients should use * the cached sStatsd via {@link #getStatsdNonblocking()}. * the cached sStatsd via {@link #getStatsdNonblocking()}. */ */ private IStatsd fetchStatsdService(StatsdDeathRecipient deathRecipient) { private IStatsd fetchStatsdServiceLocked() { synchronized (sStatsdLock) { if (sStatsd == null) { sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer .getStatsServiceManager() .getStatsServiceManager() .getStatsdServiceRegisterer() .getStatsdServiceRegisterer() .get()); .get()); if (sStatsd != null) { return sStatsd; } private void registerStatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) { StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(statsd, receivers); try { try { sStatsd.asBinder().linkToDeath(deathRecipient, /* flags */ 0); statsd.asBinder().linkToDeath(deathRecipient, /*flags=*/0); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed"); Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed"); statsdNotReadyLocked(); // Statsd has already died. Unregister receivers ourselves. for (BroadcastReceiver receiver : receivers) { mContext.unregisterReceiver(receiver); } } synchronized (sStatsdLock) { if (statsd == sStatsd) { statsdNotReadyLocked(); } } } } return sStatsd; } } } } Loading @@ -648,22 +647,23 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { * statsd. * statsd. */ */ private void sayHiToStatsd() { private void sayHiToStatsd() { if (getStatsdNonblocking() != null) { IStatsd statsd; Log.e(TAG, "Trying to fetch statsd, but it was already fetched", synchronized (sStatsdLock) { new IllegalStateException( if (sStatsd != null && sStatsd.asBinder().isBinderAlive()) { "sStatsd is not null when being fetched")); Log.e(TAG, "statsd has already been fetched before", new IllegalStateException("IStatsd object should be null or dead")); return; return; } } StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(); statsd = fetchStatsdServiceLocked(); IStatsd statsd = fetchStatsdService(deathRecipient); } if (statsd == null) { if (statsd == null) { Log.i(TAG, Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive."); "Could not yet find statsd to tell it that StatsCompanion is " + "alive."); return; return; } } mStatsManagerService.statsdReady(statsd); if (DEBUG) Log.d(TAG, "Saying hi to statsd"); if (DEBUG) Log.d(TAG, "Saying hi to statsd"); mStatsManagerService.statsdReady(statsd); try { try { statsd.statsCompanionReady(); statsd.statsCompanionReady(); Loading @@ -682,8 +682,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null); mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null); // Setup receiver for user initialize (which happens once for a new user) // Setup receiver for user initialize (which happens once for a new user) // and // and if a user is removed. // if a user is removed. filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE); filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_REMOVED); mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null); mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null); Loading @@ -691,27 +690,20 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { // Setup receiver for device reboots or shutdowns. // Setup receiver for device reboots or shutdowns. filter = new IntentFilter(Intent.ACTION_REBOOT); filter = new IntentFilter(Intent.ACTION_REBOOT); filter.addAction(Intent.ACTION_SHUTDOWN); filter.addAction(Intent.ACTION_SHUTDOWN); mContext.registerReceiverForAllUsers( mContext.registerReceiverForAllUsers(shutdownEventReceiver, filter, null, null); shutdownEventReceiver, filter, null, null); // Only add the receivers if the registration is successful. // Register death recipient. deathRecipient.addRegisteredBroadcastReceivers( List<BroadcastReceiver> broadcastReceivers = List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver)); List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver); registerStatsdDeathRecipient(statsd, broadcastReceivers); // Used so we can call statsd.bootComplete() outside of the lock. // Tell statsd that boot has completed. The signal may have already been sent, but since boolean shouldSendBootComplete = false; // the signal-receiving function is idempotent, that's ok. synchronized (sStatsdLock) { if (mBootCompleted.get()) { if (mBootCompleted && !mSentBootComplete) { mSentBootComplete = true; shouldSendBootComplete = true; } } if (shouldSendBootComplete) { statsd.bootCompleted(); statsd.bootCompleted(); } } // Pull the latest state of UID->app name, version mapping when // Pull the latest state of UID->app name, version mapping when statsd starts. // statsd starts. informAllUids(mContext); informAllUids(mContext); Log.i(TAG, "Told statsd that StatsCompanionService is alive."); Log.i(TAG, "Told statsd that StatsCompanionService is alive."); Loading @@ -722,18 +714,16 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private class StatsdDeathRecipient implements IBinder.DeathRecipient { private class StatsdDeathRecipient implements IBinder.DeathRecipient { private List<BroadcastReceiver> mReceiversToUnregister; private final IStatsd mStatsd; private final List<BroadcastReceiver> mReceiversToUnregister; StatsdDeathRecipient() { mReceiversToUnregister = new ArrayList<>(); } public void addRegisteredBroadcastReceivers(List<BroadcastReceiver> receivers) { StatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) { synchronized (sStatsdLock) { mStatsd = statsd; mReceiversToUnregister.addAll(receivers); mReceiversToUnregister = receivers; } } } // It is possible for binderDied to be called after a restarted statsd calls statsdReady, // but that's alright because the code does not assume an ordering of the two calls. @Override @Override public void binderDied() { public void binderDied() { Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers"); Loading Loading @@ -762,13 +752,19 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } } } } } // We only unregister in binder death becaseu receivers can only be unregistered // once, or an IllegalArgumentException is thrown. // Unregister receivers on death because receivers can only be unregistered once. // Otherwise, an IllegalArgumentException is thrown. for (BroadcastReceiver receiver: mReceiversToUnregister) { for (BroadcastReceiver receiver: mReceiversToUnregister) { mContext.unregisterReceiver(receiver); mContext.unregisterReceiver(receiver); } } // It's possible for statsd to have restarted and called statsdReady, causing a new // sStatsd binder object to be fetched, before the binderDied callback runs. Only // call #statsdNotReadyLocked if that hasn't happened yet. if (mStatsd == sStatsd) { statsdNotReadyLocked(); statsdNotReadyLocked(); mSentBootComplete = false; } } } } } } } Loading @@ -779,20 +775,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } void bootCompleted() { void bootCompleted() { mBootCompleted.set(true); IStatsd statsd = getStatsdNonblocking(); IStatsd statsd = getStatsdNonblocking(); synchronized (sStatsdLock) { mBootCompleted = true; if (mSentBootComplete) { // do not send a boot complete a second time. return; } if (statsd == null) { if (statsd == null) { // Statsd is not yet ready. // Statsd is not yet ready. // Delay the boot completed ping to {@link #sayHiToStatsd()} // Delay the boot completed ping to {@link #sayHiToStatsd()} return; return; } } mSentBootComplete = true; } try { try { statsd.bootCompleted(); statsd.bootCompleted(); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -808,8 +797,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } synchronized (sStatsdLock) { synchronized (sStatsdLock) { writer.println( writer.println("Number of configuration files deleted: " + mDeletedFiles.size()); "Number of configuration files deleted: " + mDeletedFiles.size()); if (mDeletedFiles.size() > 0) { if (mDeletedFiles.size() > 0) { writer.println(" timestamp, deleted file name"); writer.println(" timestamp, deleted file name"); } } Loading @@ -817,8 +805,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime(); SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime(); for (Long elapsedMillis : mDeletedFiles.keySet()) { for (Long elapsedMillis : mDeletedFiles.keySet()) { long deletionMillis = lastBootMillis + elapsedMillis; long deletionMillis = lastBootMillis + elapsedMillis; writer.println( writer.println(" " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis)); " " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis)); } } } } } } Loading
cmds/statsd/src/StatsService.cpp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -343,9 +343,11 @@ status_t StatsService::handleShellCommand(int in, int out, int err, const char** if (!utf8Args[0].compare(String8("print-logs"))) { if (!utf8Args[0].compare(String8("print-logs"))) { return cmd_print_logs(out, utf8Args); return cmd_print_logs(out, utf8Args); } } if (!utf8Args[0].compare(String8("send-active-configs"))) { if (!utf8Args[0].compare(String8("send-active-configs"))) { return cmd_trigger_active_config_broadcast(out, utf8Args); return cmd_trigger_active_config_broadcast(out, utf8Args); } } if (!utf8Args[0].compare(String8("data-subscribe"))) { if (!utf8Args[0].compare(String8("data-subscribe"))) { { { std::lock_guard<std::mutex> lock(mShellSubscriberMutex); std::lock_guard<std::mutex> lock(mShellSubscriberMutex); Loading