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.loganalysis.rule;
18 
19 import com.android.loganalysis.item.BugreportItem;
20 import com.android.loganalysis.item.LocationDumpsItem;
21 import com.android.loganalysis.item.LocationDumpsItem.LocationInfoItem;
22 
23 import java.util.concurrent.TimeUnit;
24 import java.util.ArrayList;
25 import java.util.List;
26 
27 import org.json.JSONException;
28 import org.json.JSONObject;
29 
30 
31 /**
32  * Rules definition for Location usage
33  */
34 public class LocationUsageRule extends AbstractPowerRule {
35 
36     private static final String LOCATION_USAGE_ANALYSIS = "LOCATION_USAGE_ANALYSIS";
37     private static final float LOCATION_REQUEST_DURATION_THRESHOLD = 0.1f; // 10%
38     // GSA requests for location every 285 seconds, anything more frequent is an issue
39     private static final int LOCATION_INTERVAL_THRESHOLD = 285;
40 
41     private List<LocationInfoItem> mOffendingLocationRequestList;
42     private BugreportItem mBugreportItem;
43 
LocationUsageRule(BugreportItem bugreportItem)44     public LocationUsageRule (BugreportItem bugreportItem) {
45         super(bugreportItem);
46         mBugreportItem = bugreportItem;
47     }
48 
49     @Override
applyRule()50     public void applyRule() {
51         mOffendingLocationRequestList = new ArrayList<LocationInfoItem>();
52         if (mBugreportItem.getActivityService() == null || getTimeOnBattery() <= 0) {
53             return;
54         }
55         LocationDumpsItem locationDumpsItem = mBugreportItem.getActivityService()
56                 .getLocationDumps();
57         if (locationDumpsItem == null) {
58             return;
59         }
60         final long locationRequestThresholdMs = (long) (getTimeOnBattery() *
61                 LOCATION_REQUEST_DURATION_THRESHOLD);
62 
63         for (LocationInfoItem locationClient : locationDumpsItem.getLocationClients()) {
64             final String priority = locationClient.getPriority();
65             final int effectiveIntervalSec = locationClient.getEffectiveInterval();
66             if (effectiveIntervalSec < LOCATION_INTERVAL_THRESHOLD &&
67                     !priority.equals("PRIORITY_NO_POWER") &&
68                     (TimeUnit.MINUTES.toMillis(locationClient.getDuration()) >
69                     locationRequestThresholdMs)) {
70                 mOffendingLocationRequestList.add(locationClient);
71             }
72         }
73     }
74 
75     @Override
getAnalysis()76     public JSONObject getAnalysis() {
77         JSONObject locationAnalysis = new JSONObject();
78         StringBuilder analysis = new StringBuilder();
79         if (mOffendingLocationRequestList == null || mOffendingLocationRequestList.size() <= 0) {
80             analysis.append("No apps requested for frequent location updates. ");
81         } else {
82             for (LocationInfoItem locationClient : mOffendingLocationRequestList) {
83                 analysis.append(String.format("Package %s is requesting for location "
84                         +"updates every %d secs with priority %s.", locationClient.getPackage(),
85                         locationClient.getEffectiveInterval(), locationClient.getPriority()));
86             }
87         }
88         try {
89             locationAnalysis.put(LOCATION_USAGE_ANALYSIS, analysis.toString().trim());
90         } catch (JSONException e) {
91           // do nothing
92         }
93         return locationAnalysis;
94     }
95 }
96