diff --git a/cmds/statsd/statsd.rc b/cmds/statsd/statsd.rc index 920273b5dfaa7..3a0c22425e5cc 100644 --- a/cmds/statsd/statsd.rc +++ b/cmds/statsd/statsd.rc @@ -20,5 +20,5 @@ service statsd /system/bin/statsd on post-fs-data # Create directory for statsd - mkdir /data/misc/stats-data/ 0770 statsd statsd - mkdir /data/misc/stats-service/ 0770 statsd statsd + mkdir /data/misc/stats-data/ 0770 statsd system + mkdir /data/misc/stats-service/ 0770 statsd system diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 7f95c445dd2cc..753394d25b811 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -39,6 +39,7 @@ import android.os.BatteryStatsInternal; import android.os.Binder; import android.os.Bundle; import android.os.Environment; +import android.os.FileUtils; import android.os.IBinder; import android.os.IStatsCompanionService; import android.os.IStatsManager; @@ -68,14 +69,21 @@ import com.android.internal.os.KernelUidCpuFreqTimeReader; import com.android.internal.os.KernelWakelockReader; import com.android.internal.os.KernelWakelockStats; import com.android.internal.os.PowerProfile; +import com.android.internal.util.DumpUtils; import com.android.server.LocalServices; import com.android.server.SystemService; +import java.io.File; +import java.io.FileDescriptor; import java.io.IOException; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** @@ -89,14 +97,17 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { * How long to wait on an individual subsystem to return its stats. */ private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000; + private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1); public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity"; + public static final String CONFIG_DIR = "/data/misc/stats-service"; static final String TAG = "StatsCompanionService"; static final boolean DEBUG = false; public static final int CODE_DATA_BROADCAST = 1; public static final int CODE_SUBSCRIBER_BROADCAST = 1; + public static final int DEATH_THRESHOLD = 10; private final Context mContext; private final AlarmManager mAlarmManager; @@ -119,6 +130,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { new StatFs(Environment.getRootDirectory().getAbsolutePath()); private final StatFs mStatFsTemp = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath()); + @GuardedBy("sStatsdLock") + private final HashSet mDeathTimeMillis = new HashSet<>(); + @GuardedBy("sStatsdLock") + private final HashMap mDeletedFiles = new HashMap<>(); private KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader(); private KernelCpuSpeedReader[] mKernelCpuSpeedReaders; @@ -156,7 +171,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { informAllUidsLocked(context); } catch (RemoteException e) { Slog.e(TAG, "Failed to inform statsd latest update of all apps", e); - forgetEverything(); + forgetEverythingLocked(); } } } @@ -1055,7 +1070,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { sStatsd.asBinder().linkToDeath(new StatsdDeathRecipient(), 0); } catch (RemoteException e) { Slog.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e); - forgetEverything(); + forgetEverythingLocked(); } // Setup broadcast receiver for updates. IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED); @@ -1087,7 +1102,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { Slog.i(TAG, "Told statsd that StatsCompanionService is alive."); } catch (RemoteException e) { Slog.e(TAG, "Failed to inform statsd that statscompanion is ready", e); - forgetEverything(); + forgetEverythingLocked(); } } } @@ -1096,18 +1111,60 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { @Override public void binderDied() { Slog.i(TAG, "Statsd is dead - erase all my knowledge."); - forgetEverything(); + synchronized (sStatsdLock) { + long now = SystemClock.elapsedRealtime(); + for (Long timeMillis : mDeathTimeMillis) { + long ageMillis = now - timeMillis; + if (ageMillis > MILLIS_IN_A_DAY) { + mDeathTimeMillis.remove(timeMillis); + } + } + for (Long timeMillis : mDeletedFiles.keySet()) { + long ageMillis = now - timeMillis; + if (ageMillis > MILLIS_IN_A_DAY * 7) { + mDeletedFiles.remove(timeMillis); + } + } + mDeathTimeMillis.add(now); + if (mDeathTimeMillis.size() >= DEATH_THRESHOLD) { + mDeathTimeMillis.clear(); + File[] configs = FileUtils.listFilesOrEmpty(new File(CONFIG_DIR)); + if (configs.length > 0) { + String fileName = configs[0].getName(); + if (configs[0].delete()) { + mDeletedFiles.put(now, fileName); + } + } + } + forgetEverythingLocked(); + } } } - private void forgetEverything() { + private void forgetEverythingLocked() { + sStatsd = null; + mContext.unregisterReceiver(mAppUpdateReceiver); + mContext.unregisterReceiver(mUserUpdateReceiver); + mContext.unregisterReceiver(mShutdownEventReceiver); + cancelAnomalyAlarm(); + cancelPullingAlarm(); + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return; + synchronized (sStatsdLock) { - sStatsd = null; - mContext.unregisterReceiver(mAppUpdateReceiver); - mContext.unregisterReceiver(mUserUpdateReceiver); - mContext.unregisterReceiver(mShutdownEventReceiver); - cancelAnomalyAlarm(); - cancelPullingAlarm(); + writer.println("Number of configuration files deleted: " + mDeletedFiles.size()); + if (mDeletedFiles.size() > 0) { + writer.println(" timestamp, deleted file name"); + } + long lastBootMillis = + SystemClock.currentThreadTimeMillis() - SystemClock.elapsedRealtime(); + for (Long elapsedMillis : mDeletedFiles.keySet()) { + long deletionMillis = lastBootMillis + elapsedMillis; + writer.println(" " + deletionMillis + ", " + mDeletedFiles.get(elapsedMillis)); + } } }