1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package com.android.locationtracker.data;
18 
19 import android.content.ContentValues;
20 import android.database.Cursor;
21 import android.location.Location;
22 
23 
24 /**
25  * Class that holds a tracker entry. An entry can be either a valid location, or
26  * a simple log msg
27  *
28  * It provides a concrete data structure to represent data stored in the
29  * TrackerProvider
30  */
31 class TrackerEntry {
32 
33     static final String TIMESTAMP = "Timestamp";
34     static final String TAG = "Tag";
35     static final String ENTRY_TYPE = "Type";
36 
37     private Location mLocation;
38     private float mDistFromNetLocation;
39     private String mLogMsg;
40 
41     static final String ID_COL = "_id";
42     static final String ACCURACY = "Accuracy";
43     static final String LATITUDE = "Latitude";
44     static final String LONGITUDE = "Longitude";
45     static final String ALTITUDE = "Altitude";
46     static final String SPEED = "Speed";
47     static final String BEARING = "Bearing";
48     static final String DIST_NET_LOCATION = "DistFromNetLocation";
49     static final String LOC_TIME = "LocationTime";
50     static final String DEBUG_INFO = "DebugInfo";
51 
52     static final String STRING_DATA = "STRING";
53     static final String INT_DATA = "INTEGER";
54     static final String REAL_DATA = "REAL";
55     static final String BLOB_DATA = "BLOB";
56 
57     static final String[] ATTRIBUTES = {
58             ID_COL, TIMESTAMP, TAG, ENTRY_TYPE, ACCURACY, LATITUDE, LONGITUDE,
59             ALTITUDE, SPEED, BEARING, DIST_NET_LOCATION, LOC_TIME, DEBUG_INFO};
60     static final String[] ATTRIBUTES_DATA_TYPE = {
61             INT_DATA + " PRIMARY KEY", STRING_DATA, STRING_DATA, STRING_DATA,
62             REAL_DATA, REAL_DATA, REAL_DATA, REAL_DATA, REAL_DATA, REAL_DATA,
63             REAL_DATA, INT_DATA, STRING_DATA};
64 
65     // location extra keys used to retrieve debug info
66     private static final String NETWORK_LOCATION_SOURCE_KEY =
67         "networkLocationSource";
68     private static final String NETWORK_LOCATION_TYPE_KEY =
69         "networkLocationType";
70     private static final String[] LOCATION_DEBUG_KEYS = {
71             NETWORK_LOCATION_SOURCE_KEY, NETWORK_LOCATION_TYPE_KEY};
72 
73     enum EntryType {
74         LOCATION_TYPE, LOG_TYPE
75     }
76 
77     private String mTimestamp;
78     private String mTag;
79     private EntryType mType;
80 
TrackerEntry(String tag, EntryType type)81     private TrackerEntry(String tag, EntryType type) {
82         mType = type;
83         mTag = tag;
84         mLocation = null;
85     }
86 
TrackerEntry(Location loc)87     private TrackerEntry(Location loc) {
88         this(loc.getProvider(), EntryType.LOCATION_TYPE);
89         mLocation = new Location(loc);
90     }
91 
92     /**
93      * Creates a TrackerEntry from a Location
94      */
createEntry(Location loc, float distFromNetLocation)95     static TrackerEntry createEntry(Location loc, float distFromNetLocation) {
96         TrackerEntry entry = new TrackerEntry(loc);
97 
98         String timestampVal = DateUtils.getCurrentKMLTimestamp();
99         entry.setTimestamp(timestampVal);
100         entry.setDistFromNetLocation(distFromNetLocation);
101         return entry;
102     }
103 
104     /**
105      * Creates a TrackerEntry from a log msg
106      */
createEntry(String tag, String msg)107     static TrackerEntry createEntry(String tag, String msg) {
108         TrackerEntry entry = new TrackerEntry(tag, EntryType.LOG_TYPE);
109         String timestampVal = DateUtils.getCurrentKMLTimestamp();
110         entry.setTimestamp(timestampVal);
111         entry.setLogMsg(msg);
112         return entry;
113     }
114 
setTimestamp(String timestamp)115     private void setTimestamp(String timestamp) {
116         mTimestamp = timestamp;
117     }
118 
getType()119     EntryType getType() {
120         return mType;
121     }
122 
setDistFromNetLocation(float distFromNetLocation)123     private void setDistFromNetLocation(float distFromNetLocation) {
124         mDistFromNetLocation = distFromNetLocation;
125     }
126 
setLogMsg(String msg)127     private void setLogMsg(String msg) {
128         mLogMsg = msg;
129     }
130 
setLocation(Location location)131     private void setLocation(Location location) {
132         mLocation = location;
133     }
134 
getTimestamp()135     String getTimestamp() {
136         return mTimestamp;
137     }
138 
getTag()139     String getTag() {
140         return mTag;
141     }
142 
getLocation()143     Location getLocation() {
144         return mLocation;
145     }
146 
getLogMsg()147     String getLogMsg() {
148         return mLogMsg;
149     }
150 
getDistFromNetLocation()151     float getDistFromNetLocation() {
152         return mDistFromNetLocation;
153     }
154 
buildCreationString(StringBuilder builder)155     static void buildCreationString(StringBuilder builder) {
156         if (ATTRIBUTES.length != ATTRIBUTES_DATA_TYPE.length) {
157             throw new IllegalArgumentException(
158                     "Attribute length does not match data type length");
159         }
160         for (int i = 0; i < ATTRIBUTES_DATA_TYPE.length; i++) {
161             if (i != 0) {
162                 builder.append(", ");
163             }
164             builder.append(String.format("%s %s", ATTRIBUTES[i],
165                     ATTRIBUTES_DATA_TYPE[i]));
166         }
167     }
168 
getAsContentValues()169     ContentValues getAsContentValues() {
170         ContentValues cValues = new ContentValues(ATTRIBUTES.length);
171         cValues.put(TIMESTAMP, mTimestamp);
172         cValues.put(TAG, mTag);
173         cValues.put(ENTRY_TYPE, mType.toString());
174         if (mType == EntryType.LOCATION_TYPE) {
175             cValues.put(LATITUDE, mLocation.getLatitude());
176             cValues.put(LONGITUDE, mLocation.getLongitude());
177             if (mLocation.hasAccuracy()) {
178                 cValues.put(ACCURACY, mLocation.getAccuracy());
179             }
180             if (mLocation.hasAltitude()) {
181                 cValues.put(ALTITUDE, mLocation.getAltitude());
182             }
183             if (mLocation.hasSpeed()) {
184                 cValues.put(SPEED, mLocation.getSpeed());
185             }
186             if (mLocation.hasBearing()) {
187                 cValues.put(BEARING, mLocation.getBearing());
188             }
189             cValues.put(DIST_NET_LOCATION, mDistFromNetLocation);
190             cValues.put(LOC_TIME, mLocation.getTime());
191             StringBuilder debugBuilder = new StringBuilder("");
192             if (mLocation.getExtras() != null) {
193                 for (String key : LOCATION_DEBUG_KEYS) {
194                     Object val = mLocation.getExtras().get(key);
195                     if (val != null) {
196                         debugBuilder.append(String.format("%s=%s; ", key, val
197                                 .toString()));
198                     }
199                 }
200             }
201             cValues.put(DEBUG_INFO, debugBuilder.toString());
202         } else {
203             cValues.put(DEBUG_INFO, mLogMsg);
204         }
205         return cValues;
206     }
207 
createEntry(Cursor cursor)208     static TrackerEntry createEntry(Cursor cursor) {
209         String timestamp = cursor.getString(cursor.getColumnIndex(TIMESTAMP));
210         String tag = cursor.getString(cursor.getColumnIndex(TAG));
211         String sType = cursor.getString(cursor.getColumnIndex(ENTRY_TYPE));
212         TrackerEntry entry = new TrackerEntry(tag, EntryType.valueOf(sType));
213         entry.setTimestamp(timestamp);
214         if (entry.getType() == EntryType.LOCATION_TYPE) {
215             Location location = new Location(tag);
216             location.setLatitude(cursor.getFloat(cursor
217                     .getColumnIndexOrThrow(LATITUDE)));
218             location.setLongitude(cursor.getFloat(cursor
219                     .getColumnIndexOrThrow(LONGITUDE)));
220 
221             Float accuracy = getNullableFloat(cursor, ACCURACY);
222             if (accuracy != null) {
223                 location.setAccuracy(accuracy);
224             }
225             Float altitude = getNullableFloat(cursor, ALTITUDE);
226             if (altitude != null) {
227                 location.setAltitude(altitude);
228             }
229             Float bearing = getNullableFloat(cursor, BEARING);
230             if (bearing != null) {
231                 location.setBearing(bearing);
232             }
233             Float speed = getNullableFloat(cursor, SPEED);
234             if (speed != null) {
235                 location.setSpeed(speed);
236             }
237             location.setTime(cursor.getLong(cursor.getColumnIndex(LOC_TIME)));
238             entry.setLocation(location);
239         }
240         entry.setLogMsg(cursor.getString(cursor.getColumnIndex(DEBUG_INFO)));
241 
242         return entry;
243     }
244 
getNullableFloat(Cursor cursor, String colName)245     private static Float getNullableFloat(Cursor cursor, String colName) {
246         Float retValue = null;
247         int colIndex = cursor.getColumnIndexOrThrow(colName);
248         if (!cursor.isNull(colIndex)) {
249             retValue = cursor.getFloat(colIndex);
250         }
251         return retValue;
252     }
253 }
254