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;
18 
19 import android.os.SystemClock;
20 import android.telephony.ClientRequestStats;
21 
22 import com.android.internal.annotations.VisibleForTesting;
23 
24 import java.io.PrintWriter;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 
29 public class ClientWakelockTracker {
30     public static final String LOG_TAG = "ClientWakelockTracker";
31     @VisibleForTesting
32     public HashMap<String, ClientWakelockAccountant> mClients =
33         new HashMap<String, ClientWakelockAccountant>();
34     @VisibleForTesting
35     public ArrayList<ClientWakelockAccountant> mActiveClients = new ArrayList<>();
36 
37     @VisibleForTesting
startTracking(String clientId, int requestId, int token, int numRequestsInQueue)38     public void startTracking(String clientId, int requestId, int token, int numRequestsInQueue) {
39         ClientWakelockAccountant client = getClientWakelockAccountant(clientId);
40         long uptime = SystemClock.uptimeMillis();
41         client.startAttributingWakelock(requestId, token, numRequestsInQueue, uptime);
42         updateConcurrentRequests(numRequestsInQueue, uptime);
43         synchronized (mActiveClients) {
44             if (!mActiveClients.contains(client)) {
45                 mActiveClients.add(client);
46             }
47         }
48     }
49 
50     @VisibleForTesting
stopTracking(String clientId, int requestId, int token, int numRequestsInQueue)51     public void stopTracking(String clientId, int requestId, int token, int numRequestsInQueue) {
52         ClientWakelockAccountant client = getClientWakelockAccountant(clientId);
53         long uptime = SystemClock.uptimeMillis();
54         client.stopAttributingWakelock(requestId, token, uptime);
55         if(client.getPendingRequestCount() == 0) {
56             synchronized (mActiveClients) {
57                 mActiveClients.remove(client);
58             }
59         }
60         updateConcurrentRequests(numRequestsInQueue, uptime);
61     }
62 
63     @VisibleForTesting
stopTrackingAll()64     public void stopTrackingAll() {
65         long uptime = SystemClock.uptimeMillis();
66         synchronized (mActiveClients) {
67             for (ClientWakelockAccountant client : mActiveClients) {
68                 client.stopAllPendingRequests(uptime);
69             }
70             mActiveClients.clear();
71         }
72     }
73 
getClientRequestStats()74     List<ClientRequestStats> getClientRequestStats() {
75         List<ClientRequestStats> list;
76         long uptime = SystemClock.uptimeMillis();
77         synchronized (mClients) {
78             list = new ArrayList<>(mClients.size());
79             for (String key :  mClients.keySet()) {
80                 ClientWakelockAccountant client = mClients.get(key);
81                 client.updatePendingRequestWakelockTime(uptime);
82                 list.add(new ClientRequestStats(client.mRequestStats));
83             }
84         }
85         return list;
86     }
87 
getClientWakelockAccountant(String clientId)88     private ClientWakelockAccountant getClientWakelockAccountant(String clientId) {
89         ClientWakelockAccountant client;
90         synchronized (mClients) {
91             if (mClients.containsKey(clientId)) {
92                 client = mClients.get(clientId);
93             } else {
94                 client = new ClientWakelockAccountant(clientId);
95                 mClients.put(clientId, client);
96             }
97         }
98         return client;
99     }
100 
updateConcurrentRequests(int numRequestsInQueue, long time)101     private void updateConcurrentRequests(int numRequestsInQueue, long time) {
102         if(numRequestsInQueue != 0) {
103             synchronized (mActiveClients) {
104                 for (ClientWakelockAccountant cI : mActiveClients) {
105                     cI.changeConcurrentRequests(numRequestsInQueue, time);
106                 }
107             }
108         }
109     }
110 
isClientActive(String clientId)111     public boolean isClientActive(String clientId) {
112         ClientWakelockAccountant client = getClientWakelockAccountant(clientId);
113         synchronized (mActiveClients) {
114             if (mActiveClients.contains(client)) {
115                 return true;
116             }
117         }
118 
119         return false;
120     }
121 
dumpClientRequestTracker(PrintWriter pw)122     void dumpClientRequestTracker(PrintWriter pw) {
123         pw.println("-------mClients---------------");
124         synchronized (mClients) {
125             for (String key : mClients.keySet()) {
126                 pw.println("Client : " + key);
127                 pw.println(mClients.get(key).toString());
128             }
129         }
130     }
131 }
132