1 /*
2  * Copyright (C) 2016 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 android.os.SystemClock;
20 
21 import com.android.internal.telephony.nano.TelephonyProto.SmsSession;
22 
23 import java.util.ArrayDeque;
24 import java.util.Deque;
25 import java.util.concurrent.atomic.AtomicInteger;
26 
27 /** The ongoing SMS session */
28 public class InProgressSmsSession {
29 
30     /** Maximum events stored in the session */
31     private static final int MAX_EVENTS = 20;
32 
33     /** Phone id */
34     public final int phoneId;
35 
36     /** SMS session events */
37     public final Deque<SmsSession.Event> events;
38 
39     /** Sms session starting system time in minute */
40     public final int startSystemTimeMin;
41 
42     /** Sms session starting elapsed time in milliseconds */
43     public final long startElapsedTimeMs;
44 
45     /** The last event's time */
46     private long mLastElapsedTimeMs;
47 
48     /** Indicating events dropped */
49     private boolean mEventsDropped = false;
50 
51     /** The expected SMS response #. One session could contain multiple SMS requests/responses. */
52     private AtomicInteger mNumExpectedResponses = new AtomicInteger(0);
53 
54     /** Increase the expected response # */
increaseExpectedResponse()55     public void increaseExpectedResponse() {
56         mNumExpectedResponses.incrementAndGet();
57     }
58 
59     /** Decrease the expected response # */
decreaseExpectedResponse()60     public void decreaseExpectedResponse() {
61         mNumExpectedResponses.decrementAndGet();
62     }
63 
64     /** Get the expected response # */
getNumExpectedResponses()65     public int getNumExpectedResponses() {
66         return mNumExpectedResponses.get();
67     }
68 
69     /** Check if events dropped */
isEventsDropped()70     public boolean isEventsDropped() { return mEventsDropped; }
71 
72     /**
73      * Constructor
74      *
75      * @param phoneId Phone id
76      */
InProgressSmsSession(int phoneId)77     public InProgressSmsSession(int phoneId) {
78         this.phoneId = phoneId;
79         events = new ArrayDeque<>();
80         // Save session start with lowered precision due to the privacy requirements
81         startSystemTimeMin = TelephonyMetrics.roundSessionStart(System.currentTimeMillis());
82         startElapsedTimeMs = SystemClock.elapsedRealtime();
83         mLastElapsedTimeMs = startElapsedTimeMs;
84     }
85 
86     /**
87      * Add event
88      *
89      * @param builder Event builder
90      */
addEvent(SmsSessionEventBuilder builder)91     public void addEvent(SmsSessionEventBuilder builder) {
92         addEvent(SystemClock.elapsedRealtime(), builder);
93     }
94 
95     /**
96      * Add event
97      *
98      * @param timestamp Timestamp to be recoded with the event
99      * @param builder Event builder
100      */
addEvent(long timestamp, SmsSessionEventBuilder builder)101     public synchronized void addEvent(long timestamp, SmsSessionEventBuilder builder) {
102         if (events.size() >= MAX_EVENTS) {
103             events.removeFirst();
104             mEventsDropped = true;
105         }
106 
107         builder.setDelay(TelephonyMetrics.toPrivacyFuzzedTimeInterval(
108                 mLastElapsedTimeMs, timestamp));
109 
110         events.add(builder.build());
111         mLastElapsedTimeMs = timestamp;
112     }
113 }
114