1/*
2 * Copyright (C) 2015 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.am;
18
19import android.app.ActivityOptions;
20import android.app.PendingIntent;
21import android.content.Context;
22import android.content.Intent;
23import android.os.Bundle;
24import android.os.SystemClock;
25import android.util.ArrayMap;
26import android.util.MutableLong;
27import android.util.TimeUtils;
28
29import java.io.PrintWriter;
30
31/**
32 * Tracks the time a user spent in an app.
33 */
34public class AppTimeTracker {
35    private final PendingIntent mReceiver;
36
37    private long mTotalTime;
38    private final ArrayMap<String, MutableLong> mPackageTimes = new ArrayMap<>();
39
40    private long mStartedTime;
41    private String mStartedPackage;
42    private MutableLong mStartedPackageTime;
43
44    public AppTimeTracker(PendingIntent receiver) {
45        mReceiver = receiver;
46    }
47
48    public void start(String packageName) {
49        long now = SystemClock.elapsedRealtime();
50        if (mStartedTime == 0) {
51            mStartedTime = now;
52        }
53        if (!packageName.equals(mStartedPackage)) {
54            if (mStartedPackageTime != null) {
55                long elapsedTime = now - mStartedTime;
56                mStartedPackageTime.value += elapsedTime;
57                mTotalTime += elapsedTime;
58            }
59            mStartedPackage = packageName;
60            mStartedPackageTime = mPackageTimes.get(packageName);
61            if (mStartedPackageTime == null) {
62                mStartedPackageTime = new MutableLong(0);
63                mPackageTimes.put(packageName, mStartedPackageTime);
64            }
65        }
66    }
67
68    public void stop() {
69        if (mStartedTime != 0) {
70            long elapsedTime = SystemClock.elapsedRealtime() - mStartedTime;
71            mTotalTime += elapsedTime;
72            if (mStartedPackageTime != null) {
73                mStartedPackageTime.value += elapsedTime;
74            }
75            mStartedPackage = null;
76            mStartedPackageTime = null;
77        }
78    }
79
80    public void deliverResult(Context context) {
81        stop();
82        Bundle extras = new Bundle();
83        extras.putLong(ActivityOptions.EXTRA_USAGE_TIME_REPORT, mTotalTime);
84        Bundle pkgs = new Bundle();
85        for (int i=mPackageTimes.size()-1; i>=0; i--) {
86            pkgs.putLong(mPackageTimes.keyAt(i), mPackageTimes.valueAt(i).value);
87        }
88        extras.putBundle(ActivityOptions.EXTRA_USAGE_TIME_REPORT_PACKAGES, pkgs);
89        Intent fillinIntent = new Intent();
90        fillinIntent.putExtras(extras);
91        try {
92            mReceiver.send(context, 0, fillinIntent);
93        } catch (PendingIntent.CanceledException e) {
94        }
95    }
96
97    public void dumpWithHeader(PrintWriter pw, String prefix, boolean details) {
98        pw.print(prefix); pw.print("AppTimeTracker #");
99        pw.print(Integer.toHexString(System.identityHashCode(this)));
100        pw.println(":");
101        dump(pw, prefix + "  ", details);
102    }
103
104    public void dump(PrintWriter pw, String prefix, boolean details) {
105        pw.print(prefix); pw.print("mReceiver="); pw.println(mReceiver);
106        pw.print(prefix); pw.print("mTotalTime=");
107        TimeUtils.formatDuration(mTotalTime, pw);
108        pw.println();
109        for (int i = 0; i < mPackageTimes.size(); i++) {
110            pw.print(prefix); pw.print("mPackageTime:"); pw.print(mPackageTimes.keyAt(i));
111            pw.print("=");
112            TimeUtils.formatDuration(mPackageTimes.valueAt(i).value, pw);
113            pw.println();
114        }
115        if (details && mStartedTime != 0) {
116            pw.print(prefix); pw.print("mStartedTime=");
117            TimeUtils.formatDuration(SystemClock.elapsedRealtime(), mStartedTime, pw);
118            pw.println();
119            pw.print(prefix); pw.print("mStartedPackage="); pw.println(mStartedPackage);
120        }
121    }
122}
123