/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.stats;

import static android.os.Process.THREAD_PRIORITY_BACKGROUND;

import android.app.AlarmManager;
import android.app.AlarmManager.OnAlarmListener;
import android.app.StatsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IStatsCompanionService;
import android.os.IStatsd;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.StatsFrameworkInitializer;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Helper service for statsd (the native stats management service in cmds/statsd/).
 * Used for registering and receiving alarms on behalf of statsd.
 *
 * @hide
 */
public class StatsCompanionService extends IStatsCompanionService.Stub {

    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;
    /**
     * Hard coded field ids of frameworks/base/cmds/statsd/src/uid_data.proto
     * to be used in ProtoOutputStream.
     */
    private static final int APPLICATION_INFO_FIELD_ID = 1;
    private static final int UID_FIELD_ID = 1;
    private static final int VERSION_FIELD_ID = 2;
    private static final int VERSION_STRING_FIELD_ID = 3;
    private static final int PACKAGE_NAME_FIELD_ID = 4;
    private static final int INSTALLER_FIELD_ID = 5;

    public static final int DEATH_THRESHOLD = 10;

    static final class CompanionHandler extends Handler {
        CompanionHandler(Looper looper) {
            super(looper);
        }
    }

    private final Context mContext;
    private final AlarmManager mAlarmManager;
    @GuardedBy("sStatsdLock")
    private static IStatsd sStatsd;
    private static final Object sStatsdLock = new Object();

    private final OnAlarmListener mPullingAlarmListener;
    private final OnAlarmListener mPeriodicAlarmListener;

    private StatsManagerService mStatsManagerService;

    @GuardedBy("sStatsdLock")
    private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
    @GuardedBy("sStatsdLock")
    private final HashMap<Long, String> mDeletedFiles = new HashMap<>();
    private final CompanionHandler mHandler;

    // Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle.
    private AtomicBoolean mBootCompleted = new AtomicBoolean(false);

    public StatsCompanionService(Context context) {
        super();
        mContext = context;
        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED.");
        HandlerThread handlerThread = new HandlerThread(TAG);
        handlerThread.start();
        mHandler = new CompanionHandler(handlerThread.getLooper());

        mPullingAlarmListener = new PullingAlarmListener(context);
        mPeriodicAlarmListener = new PeriodicAlarmListener(context);
    }

    private final static int[] toIntArray(List<Integer> list) {
        int[] ret = new int[list.size()];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = list.get(i);
        }
        return ret;
    }

    private final static long[] toLongArray(List<Long> list) {
        long[] ret = new long[list.size()];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = list.get(i);
        }
        return ret;
    }

    /**
     * Non-blocking call to retrieve a reference to statsd
     *
     * @return IStatsd object if statsd is ready, null otherwise.
     */
    private static IStatsd getStatsdNonblocking() {
        synchronized (sStatsdLock) {
            return sStatsd;
        }
    }

    private static void informAllUids(Context context) {
        ParcelFileDescriptor[] fds;
        try {
            fds = ParcelFileDescriptor.createPipe();
        } catch (IOException e) {
            Log.e(TAG, "Failed to create a pipe to send uid map data.", e);
            return;
        }
        HandlerThread backgroundThread = new HandlerThread(
                "statsCompanionService.bg", THREAD_PRIORITY_BACKGROUND);
        backgroundThread.start();
        Handler handler = new Handler(backgroundThread.getLooper());
        handler.post(() -> {
            UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
            PackageManager pm = context.getPackageManager();
            final List<UserHandle> users = um.getUserHandles(true);
            if (DEBUG) {
                Log.d(TAG, "Iterating over " + users.size() + " userHandles.");
            }
            IStatsd statsd = getStatsdNonblocking();
            if (statsd == null) {
                return;
            }
            try {
                statsd.informAllUidData(fds[0]);
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to send uid map to statsd");
            }
            try {
                fds[0].close();
            } catch (IOException e) {
                Log.e(TAG, "Failed to close the read side of the pipe.", e);
            }
            final ParcelFileDescriptor writeFd = fds[1];
            FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(writeFd);
            try {
                ProtoOutputStream output = new ProtoOutputStream(fout);
                int numRecords = 0;
                // Add in all the apps for every user/profile.
                for (UserHandle userHandle : users) {
                    List<PackageInfo> packagesPlusApex = getAllPackagesWithApex(pm, userHandle);
                    for (int j = 0; j < packagesPlusApex.size(); j++) {
                        if (packagesPlusApex.get(j).applicationInfo != null) {
                            String installer;
                            try {
                                installer = pm.getInstallerPackageName(
                                        packagesPlusApex.get(j).packageName);
                            } catch (IllegalArgumentException e) {
                                installer = "";
                            }
                            long applicationInfoToken =
                                    output.start(ProtoOutputStream.FIELD_TYPE_MESSAGE
                                            | ProtoOutputStream.FIELD_COUNT_REPEATED
                                            | APPLICATION_INFO_FIELD_ID);
                            output.write(ProtoOutputStream.FIELD_TYPE_INT32
                                            | ProtoOutputStream.FIELD_COUNT_SINGLE | UID_FIELD_ID,
                                    packagesPlusApex.get(j).applicationInfo.uid);
                            output.write(ProtoOutputStream.FIELD_TYPE_INT64
                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
                                            | VERSION_FIELD_ID,
                                    packagesPlusApex.get(j).getLongVersionCode());
                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
                                            | VERSION_STRING_FIELD_ID,
                                    packagesPlusApex.get(j).versionName);
                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
                                    | ProtoOutputStream.FIELD_COUNT_SINGLE
                                    | PACKAGE_NAME_FIELD_ID, packagesPlusApex.get(j).packageName);
                            output.write(ProtoOutputStream.FIELD_TYPE_STRING
                                            | ProtoOutputStream.FIELD_COUNT_SINGLE
                                            | INSTALLER_FIELD_ID,
                                    installer == null ? "" : installer);
                            numRecords++;
                            output.end(applicationInfoToken);
                        }
                    }
                }
                output.flush();
                if (DEBUG) {
                    Log.d(TAG, "Sent data for " + numRecords + " apps");
                }
            } finally {
                FileUtils.closeQuietly(fout);
                backgroundThread.quit();
                backgroundThread.interrupt();
            }
        });
    }

    private static List<PackageInfo> getAllPackagesWithApex(PackageManager pm,
            UserHandle userHandle) {
        // We want all the uninstalled packages because uninstalled package uids can still be logged
        // to statsd.
        List<PackageInfo> allPackages = new ArrayList<>(
                pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES
                                | PackageManager.MATCH_ANY_USER,
                        userHandle.getIdentifier()));
        // We make a second query to package manager for the apex modules because package manager
        // returns both installed and uninstalled apexes with
        // PackageManager.MATCH_UNINSTALLED_PACKAGES flag. We only want active apexes because
        // inactive apexes can conflict with active ones.
        for (PackageInfo packageInfo : pm.getInstalledPackages(PackageManager.MATCH_APEX)) {
            if (packageInfo.isApex) {
                allPackages.add(packageInfo);
            }
        }
        return allPackages;
    }

    private static class WakelockThread extends Thread {
        private final PowerManager.WakeLock mWl;
        private final Runnable mRunnable;

        WakelockThread(Context context, String wakelockName, Runnable runnable) {
            PowerManager powerManager = (PowerManager)
                    context.getSystemService(Context.POWER_SERVICE);
            mWl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakelockName);
            mRunnable = runnable;
        }
        @Override
        public void run() {
            try {
                mRunnable.run();
            } finally {
                mWl.release();
            }
        }
        @Override
        public void start() {
            mWl.acquire();
            super.start();
        }
    }

    private final static class AppUpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            /**
             * App updates actually consist of REMOVE, ADD, and then REPLACE broadcasts. To avoid
             * waste, we ignore the REMOVE and ADD broadcasts that contain the replacing flag.
             * If we can't find the value for EXTRA_REPLACING, we default to false.
             */
            if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)
                    && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                return; // Keep only replacing or normal add and remove.
            }
            if (DEBUG) Log.d(TAG, "StatsCompanionService noticed an app was updated.");
            synchronized (sStatsdLock) {
                if (sStatsd == null) {
                    Log.w(TAG, "Could not access statsd to inform it of an app update");
                    return;
                }
                try {
                    if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
                        Bundle b = intent.getExtras();
                        int uid = b.getInt(Intent.EXTRA_UID);
                        boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                        if (!replacing) {
                            // Don't bother sending an update if we're right about to get another
                            // intent for the new version that's added.
                            String app = intent.getData().getSchemeSpecificPart();
                            sStatsd.informOnePackageRemoved(app, uid);
                        }
                    } else {
                        PackageManager pm = context.getPackageManager();
                        Bundle b = intent.getExtras();
                        int uid = b.getInt(Intent.EXTRA_UID);
                        String app = intent.getData().getSchemeSpecificPart();
                        PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
                        String installer;
                        try {
                            installer = pm.getInstallerPackageName(app);
                        } catch (IllegalArgumentException e) {
                            installer = "";
                        }
                        sStatsd.informOnePackage(
                                app,
                                uid,
                                pi.getLongVersionCode(),
                                pi.versionName == null ? "" : pi.versionName,
                                installer == null ? "" : installer);
                    }
                } catch (Exception e) {
                    Log.w(TAG, "Failed to inform statsd of an app update", e);
                }
            }
        }
    }

    private static final class UserUpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Pull the latest state of UID->app name, version mapping.
            // Needed since the new user basically has a version of every app.
            informAllUids(context);
        }
    }

    public final static class PullingAlarmListener implements OnAlarmListener {
        private final Context mContext;

        PullingAlarmListener(Context context) {
            mContext = context;
        }

        @Override
        public void onAlarm() {
            if (DEBUG) {
                Log.d(TAG, "Time to poll something.");
            }
            IStatsd statsd = getStatsdNonblocking();
            if (statsd == null) {
                Log.w(TAG, "Could not access statsd to inform it of pulling alarm firing.");
                return;
            }

            // Wakelock needs to be retained while calling statsd.
            Thread thread = new WakelockThread(mContext,
                    PullingAlarmListener.class.getCanonicalName(), new Runnable() {
                        @Override
                        public void run() {
                            try {
                                statsd.informPollAlarmFired();
                            } catch (RemoteException e) {
                                Log.w(TAG, "Failed to inform statsd of pulling alarm firing.", e);
                            }
                        }
                    });
            thread.start();
        }
    }

    public final static class PeriodicAlarmListener implements OnAlarmListener {
        private final Context mContext;

        PeriodicAlarmListener(Context context) {
            mContext = context;
        }

        @Override
        public void onAlarm() {
            if (DEBUG) {
                Log.d(TAG, "Time to trigger periodic alarm.");
            }
            IStatsd statsd = getStatsdNonblocking();
            if (statsd == null) {
                Log.w(TAG, "Could not access statsd to inform it of periodic alarm firing.");
                return;
            }

            // Wakelock needs to be retained while calling statsd.
            Thread thread = new WakelockThread(mContext,
                    PeriodicAlarmListener.class.getCanonicalName(), new Runnable() {
                        @Override
                        public void run() {
                            try {
                                statsd.informAlarmForSubscriberTriggeringFired();
                            } catch (RemoteException e) {
                                Log.w(TAG, "Failed to inform statsd of periodic alarm firing.", e);
                            }
                        }
                    });
            thread.start();
        }
    }

    public final static class ShutdownEventReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            /**
             * Skip immediately if intent is not relevant to device shutdown.
             */
            if (!intent.getAction().equals(Intent.ACTION_REBOOT)
                    && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN)
                    && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) {
                return;
            }

            if (DEBUG) {
                Log.i(TAG, "StatsCompanionService noticed a shutdown.");
            }
            IStatsd statsd = getStatsdNonblocking();
            if (statsd == null) {
                Log.w(TAG, "Could not access statsd to inform it of a shutdown event.");
                return;
            }
            try {
                // two way binder call
                statsd.informDeviceShutdown();
            } catch (Exception e) {
                Log.w(TAG, "Failed to inform statsd of a shutdown event.", e);
            }
        }
    }

    @Override // Binder call
    public void setAlarmForSubscriberTriggering(long timestampMs) {
        StatsCompanion.enforceStatsdCallingUid();
        if (DEBUG) {
            Log.d(TAG,
                    "Setting periodic alarm in about " + (timestampMs
                            - SystemClock.elapsedRealtime()));
        }
        final long callingToken = Binder.clearCallingIdentity();
        try {
            // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
            // only fire when it awakens.
            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".periodic",
                    mPeriodicAlarmListener, mHandler);
        } finally {
            Binder.restoreCallingIdentity(callingToken);
        }
    }

    @Override // Binder call
    public void cancelAlarmForSubscriberTriggering() {
        StatsCompanion.enforceStatsdCallingUid();
        if (DEBUG) {
            Log.d(TAG, "Cancelling periodic alarm");
        }
        final long callingToken = Binder.clearCallingIdentity();
        try {
            mAlarmManager.cancel(mPeriodicAlarmListener);
        } finally {
            Binder.restoreCallingIdentity(callingToken);
        }
    }

    @Override // Binder call
    public void setPullingAlarm(long nextPullTimeMs) {
        StatsCompanion.enforceStatsdCallingUid();
        if (DEBUG) {
            Log.d(TAG, "Setting pulling alarm in about "
                    + (nextPullTimeMs - SystemClock.elapsedRealtime()));
        }
        final long callingToken = Binder.clearCallingIdentity();
        try {
            // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
            // only fire when it awakens.
            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextPullTimeMs, TAG + ".pull",
                    mPullingAlarmListener, mHandler);
        } finally {
            Binder.restoreCallingIdentity(callingToken);
        }
    }

    @Override // Binder call
    public void cancelPullingAlarm() {
        StatsCompanion.enforceStatsdCallingUid();
        if (DEBUG) {
            Log.d(TAG, "Cancelling pulling alarm");
        }
        final long callingToken = Binder.clearCallingIdentity();
        try {
            mAlarmManager.cancel(mPullingAlarmListener);
        } finally {
            Binder.restoreCallingIdentity(callingToken);
        }
    }

    @Override // Binder call
    public void statsdReady() {
        StatsCompanion.enforceStatsdCallingUid();
        if (DEBUG) {
            Log.d(TAG, "learned that statsdReady");
        }
        sayHiToStatsd(); // tell statsd that we're ready too and link to it

        final Intent intent = new Intent(StatsManager.ACTION_STATSD_STARTED);
        // Retrieve list of broadcast receivers for this broadcast & send them directed broadcasts
        // to wake them up (if they're in background).
        List<ResolveInfo> resolveInfos =
                mContext.getPackageManager().queryBroadcastReceiversAsUser(
                        intent, 0, UserHandle.SYSTEM);
        if (resolveInfos == null || resolveInfos.isEmpty()) {
            return; // No need to send broadcast.
        }

        for (ResolveInfo resolveInfo : resolveInfos) {
            Intent intentToSend = new Intent(intent);
            intentToSend.setComponent(new ComponentName(
                    resolveInfo.activityInfo.applicationInfo.packageName,
                    resolveInfo.activityInfo.name));
            mContext.sendBroadcastAsUser(intentToSend, UserHandle.SYSTEM,
                    android.Manifest.permission.DUMP);
        }
    }

    @Override // Binder call
    public boolean checkPermission(String permission, int pid, int uid) {
        StatsCompanion.enforceStatsdCallingUid();
        return mContext.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED;
    }

    // Statsd related code

    /**
     * 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
     * the cached sStatsd via {@link #getStatsdNonblocking()}.
     */
    private IStatsd fetchStatsdServiceLocked() {
        sStatsd = IStatsd.Stub.asInterface(StatsFrameworkInitializer
                .getStatsServiceManager()
                .getStatsdServiceRegisterer()
                .get());
        return sStatsd;
    }

    private void registerStatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) {
        StatsdDeathRecipient deathRecipient = new StatsdDeathRecipient(statsd, receivers);

        try {
            statsd.asBinder().linkToDeath(deathRecipient, /*flags=*/0);
        } catch (RemoteException e) {
            Log.e(TAG, "linkToDeath (StatsdDeathRecipient) failed");
            // Statsd has already died. Unregister receivers ourselves.
            for (BroadcastReceiver receiver : receivers) {
                mContext.unregisterReceiver(receiver);
            }
            synchronized (sStatsdLock) {
                if (statsd == sStatsd) {
                    statsdNotReadyLocked();
                }
            }
        }
    }

    /**
     * Now that the android system is ready, StatsCompanion is ready too, so inform statsd.
     */
    void systemReady() {
        if (DEBUG) Log.d(TAG, "Learned that systemReady");
        sayHiToStatsd();
    }

    void setStatsManagerService(StatsManagerService statsManagerService) {
        mStatsManagerService = statsManagerService;
    }

    /**
     * Tells statsd that statscompanion is ready. If the binder call returns, link to
     * statsd.
     */
    private void sayHiToStatsd() {
        IStatsd statsd;
        synchronized (sStatsdLock) {
            if (sStatsd != null && sStatsd.asBinder().isBinderAlive()) {
                Log.e(TAG, "statsd has already been fetched before",
                        new IllegalStateException("IStatsd object should be null or dead"));
                return;
            }
            statsd = fetchStatsdServiceLocked();
        }

        if (statsd == null) {
            Log.i(TAG, "Could not yet find statsd to tell it that StatsCompanion is alive.");
            return;
        }

        // Cleann up from previous statsd - cancel any alarms that had been set. Do this here
        // instead of in binder death because statsd can come back and set different alarms, or not
        // want to set an alarm when it had been set. This guarantees that when we get a new statsd,
        // we cancel any alarms before it is able to set them.
        cancelPullingAlarm();
        cancelAlarmForSubscriberTriggering();

        if (DEBUG) Log.d(TAG, "Saying hi to statsd");
        mStatsManagerService.statsdReady(statsd);
        try {
            statsd.statsCompanionReady();

            BroadcastReceiver appUpdateReceiver = new AppUpdateReceiver();
            BroadcastReceiver userUpdateReceiver = new UserUpdateReceiver();
            BroadcastReceiver shutdownEventReceiver = new ShutdownEventReceiver();

            // Setup broadcast receiver for updates.
            IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REPLACED);
            filter.addAction(Intent.ACTION_PACKAGE_ADDED);
            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
            filter.addDataScheme("package");
            mContext.registerReceiverForAllUsers(appUpdateReceiver, filter, null, null);

            // Setup receiver for user initialize (which happens once for a new user)
            // and if a user is removed.
            filter = new IntentFilter(Intent.ACTION_USER_INITIALIZE);
            filter.addAction(Intent.ACTION_USER_REMOVED);
            mContext.registerReceiverForAllUsers(userUpdateReceiver, filter, null, null);

            // Setup receiver for device reboots or shutdowns.
            filter = new IntentFilter(Intent.ACTION_REBOOT);
            filter.addAction(Intent.ACTION_SHUTDOWN);
            mContext.registerReceiverForAllUsers(shutdownEventReceiver, filter, null, null);

            // Register death recipient.
            List<BroadcastReceiver> broadcastReceivers =
                    List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver);
            registerStatsdDeathRecipient(statsd, broadcastReceivers);

            // Tell statsd that boot has completed. The signal may have already been sent, but since
            // the signal-receiving function is idempotent, that's ok.
            if (mBootCompleted.get()) {
                statsd.bootCompleted();
            }

            // Pull the latest state of UID->app name, version mapping when statsd starts.
            informAllUids(mContext);

            Log.i(TAG, "Told statsd that StatsCompanionService is alive.");
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to inform statsd that statscompanion is ready", e);
        }
    }

    private class StatsdDeathRecipient implements IBinder.DeathRecipient {

        private final IStatsd mStatsd;
        private final List<BroadcastReceiver> mReceiversToUnregister;

        StatsdDeathRecipient(IStatsd statsd, List<BroadcastReceiver> receivers) {
            mStatsd = statsd;
            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
        public void binderDied() {
            Log.i(TAG, "Statsd is dead - erase all my knowledge, except pullers");
            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 = new File(CONFIG_DIR).listFiles();
                    if (configs != null && configs.length > 0) {
                        String fileName = configs[0].getName();
                        if (configs[0].delete()) {
                            mDeletedFiles.put(now, fileName);
                        }
                    }
                }

                // Unregister receivers on death because receivers can only be unregistered once.
                // Otherwise, an IllegalArgumentException is thrown.
                for (BroadcastReceiver receiver: mReceiversToUnregister) {
                    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();
                }
            }
        }
    }

    private void statsdNotReadyLocked() {
        sStatsd = null;
        mStatsManagerService.statsdNotReady();
    }

    void bootCompleted() {
        mBootCompleted.set(true);
        IStatsd statsd = getStatsdNonblocking();
        if (statsd == null) {
            // Statsd is not yet ready.
            // Delay the boot completed ping to {@link #sayHiToStatsd()}
            return;
        }
        try {
            statsd.bootCompleted();
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to notify statsd that boot completed");
        }
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        synchronized (sStatsdLock) {
            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));
            }
        }
    }
}
