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 
17 package com.android.server.am;
18 
19 import android.app.ActivityOptions;
20 import android.app.PendingIntent;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.os.SystemClock;
25 import android.util.ArrayMap;
26 import android.util.MutableLong;
27 import android.util.TimeUtils;
28 
29 import java.io.PrintWriter;
30 
31 /**
32  * Tracks the time a user spent in an app.
33  */
34 public 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 
AppTimeTracker(PendingIntent receiver)44     public AppTimeTracker(PendingIntent receiver) {
45         mReceiver = receiver;
46     }
47 
start(String packageName)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 
stop()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 
deliverResult(Context context)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 
dumpWithHeader(PrintWriter pw, String prefix, boolean details)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 
dump(PrintWriter pw, String prefix, boolean details)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