1 /*
2  * Copyright (C) 2020 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.internal.telephony.metrics;
18 
19 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
20 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
21 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
22 
23 import android.app.StatsManager;
24 import android.content.Context;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.telephony.Rlog;
28 
29 import java.util.Random;
30 
31 /**
32  * Implements statsd pullers for Telephony.
33  *
34  * <p>This class is currently a stub. When statsd pulled atom support is merged, this class will
35  * register pullers to statsd, which will be called once a day to obtain telephony statistics that
36  * cannot be sent to statsd in real time.
37  */
38 public class MetricsCollector {
39     private static final String TAG = MetricsCollector.class.getSimpleName();
40 
41     /** Disables various restrictions to ease debugging during development. */
42     private static final boolean DBG = false; // STOPSHIP if true
43 
44     /**
45      * Sets atom pull cool down to 23 hours to help enforcing privacy requirement.
46      *
47      * <p>Applies to certain atoms. The interval of 23 hours leaves some margin for pull operations
48      * that occur once a day.
49      */
50     private static final long MIN_COOLDOWN_MILLIS =
51             DBG ? 10L * SECOND_IN_MILLIS : 23L * HOUR_IN_MILLIS;
52 
53     /**
54      * Buckets with less than these many calls will be dropped.
55      *
56      * <p>Applies to metrics with duration fields. Currently used by voice call RAT usages.
57      */
58     private static final long MIN_CALLS_PER_BUCKET = DBG ? 0L : 5L;
59 
60     /** Bucket size in milliseconds to round call durations into. */
61     private static final long DURATION_BUCKET_MILLIS =
62             DBG ? 2L * SECOND_IN_MILLIS : 5L * MINUTE_IN_MILLIS;
63 
64     private PersistAtomsStorage mStorage;
65     private final StatsManager mStatsManager;
66     private static final Random sRandom = new Random();
67 
MetricsCollector(Context context)68     public MetricsCollector(Context context) {
69         mStorage = new PersistAtomsStorage(context);
70         mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER);
71         if (mStatsManager != null) {
72             // TODO: registration/puller needs to be added and the following code needs to be
73             // enabled once dependencies are available.
74             /*
75             registerAtom(SIM_SLOT_STATE, null);
76             registerAtom(SUPPORTED_RADIO_ACCESS_FAMILY, null);
77             registerAtom(VOICE_CALL_RAT_USAGE, POLICY_PULL_DAILY);
78             registerAtom(VOICE_CALL_SESSION, POLICY_PULL_DAILY);
79             Rlog.d(TAG, "registered");
80             */
81         } else {
82             Rlog.e(TAG, "could not get StatsManager, atoms not registered");
83         }
84     }
85 
86     /** Replaces the {@link PersistAtomsStorage} backing the puller. Used during unit tests. */
87     @VisibleForTesting
setPersistAtomsStorage(PersistAtomsStorage storage)88     public void setPersistAtomsStorage(PersistAtomsStorage storage) {
89         mStorage = storage;
90     }
91 
92     /** Returns the {@link PersistAtomsStorage} backing the puller. */
getAtomsStorage()93     public PersistAtomsStorage getAtomsStorage() {
94         return mStorage;
95     }
96 
97     /** Returns the value rounded to the bucket. */
round(long value, long bucket)98     private static long round(long value, long bucket) {
99         return ((value + bucket / 2) / bucket) * bucket;
100     }
101 }
102