Home | History | Annotate | Download | only in location
      1 /*
      2  * Copyright (C) 2008 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.server.location;
     18 
     19 import android.net.TrafficStats;
     20 import android.text.TextUtils;
     21 import android.util.Log;
     22 
     23 import java.io.ByteArrayOutputStream;
     24 import java.io.IOException;
     25 import java.io.InputStream;
     26 import java.net.HttpURLConnection;
     27 import java.net.URL;
     28 import java.util.Properties;
     29 import java.util.Random;
     30 import java.util.concurrent.TimeUnit;
     31 
     32 /**
     33  * A class for downloading GPS XTRA data.
     34  *
     35  * {@hide}
     36  */
     37 public class GpsXtraDownloader {
     38 
     39     private static final String TAG = "GpsXtraDownloader";
     40     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     41     private static final long MAXIMUM_CONTENT_LENGTH_BYTES = 1000000;  // 1MB.
     42     private static final String DEFAULT_USER_AGENT = "Android";
     43     private static final int CONNECTION_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(30);
     44     private static final int READ_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(60);
     45 
     46     private final String[] mXtraServers;
     47     // to load balance our server requests
     48     private int mNextServerIndex;
     49     private final String mUserAgent;
     50 
     51     GpsXtraDownloader(Properties properties) {
     52         // read XTRA servers from the Properties object
     53         int count = 0;
     54         String server1 = properties.getProperty("XTRA_SERVER_1");
     55         String server2 = properties.getProperty("XTRA_SERVER_2");
     56         String server3 = properties.getProperty("XTRA_SERVER_3");
     57         if (server1 != null) count++;
     58         if (server2 != null) count++;
     59         if (server3 != null) count++;
     60 
     61         // Set User Agent from properties, if possible.
     62         String agent = properties.getProperty("XTRA_USER_AGENT");
     63         if (TextUtils.isEmpty(agent)) {
     64             mUserAgent = DEFAULT_USER_AGENT;
     65         } else {
     66             mUserAgent = agent;
     67         }
     68 
     69         if (count == 0) {
     70             Log.e(TAG, "No XTRA servers were specified in the GPS configuration");
     71             mXtraServers = null;
     72         } else {
     73             mXtraServers = new String[count];
     74             count = 0;
     75             if (server1 != null) mXtraServers[count++] = server1;
     76             if (server2 != null) mXtraServers[count++] = server2;
     77             if (server3 != null) mXtraServers[count++] = server3;
     78 
     79             // randomize first server
     80             Random random = new Random();
     81             mNextServerIndex = random.nextInt(count);
     82         }
     83     }
     84 
     85     byte[] downloadXtraData() {
     86         byte[] result = null;
     87         int startIndex = mNextServerIndex;
     88 
     89         if (mXtraServers == null) {
     90             return null;
     91         }
     92 
     93         // load balance our requests among the available servers
     94         while (result == null) {
     95             final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_GPS);
     96             try {
     97                 result = doDownload(mXtraServers[mNextServerIndex]);
     98             } finally {
     99                 TrafficStats.setThreadStatsTag(oldTag);
    100             }
    101 
    102             // increment mNextServerIndex and wrap around if necessary
    103             mNextServerIndex++;
    104             if (mNextServerIndex == mXtraServers.length) {
    105                 mNextServerIndex = 0;
    106             }
    107             // break if we have tried all the servers
    108             if (mNextServerIndex == startIndex) break;
    109         }
    110 
    111         return result;
    112     }
    113 
    114     protected byte[] doDownload(String url) {
    115         if (DEBUG) Log.d(TAG, "Downloading XTRA data from " + url);
    116 
    117         HttpURLConnection connection = null;
    118         try {
    119             connection = (HttpURLConnection) (new URL(url)).openConnection();
    120             connection.setRequestProperty(
    121                     "Accept",
    122                     "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic");
    123             connection.setRequestProperty(
    124                     "x-wap-profile",
    125                     "http://www.openmobilealliance.org/tech/profiles/UAPROF/ccppschema-20021212#");
    126             connection.setConnectTimeout(CONNECTION_TIMEOUT_MS);
    127             connection.setReadTimeout(READ_TIMEOUT_MS);
    128 
    129             connection.connect();
    130             int statusCode = connection.getResponseCode();
    131             if (statusCode != HttpURLConnection.HTTP_OK) {
    132                 if (DEBUG) Log.d(TAG, "HTTP error downloading gps XTRA: " + statusCode);
    133                 return null;
    134             }
    135 
    136             try (InputStream in = connection.getInputStream()) {
    137                 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    138                 byte[] buffer = new byte[1024];
    139                 int count;
    140                 while ((count = in.read(buffer)) != -1) {
    141                     bytes.write(buffer, 0, count);
    142                     if (bytes.size() > MAXIMUM_CONTENT_LENGTH_BYTES) {
    143                         if (DEBUG) Log.d(TAG, "XTRA file too large");
    144                         return null;
    145                     }
    146                 }
    147                 return bytes.toByteArray();
    148             }
    149         } catch (IOException ioe) {
    150             if (DEBUG) Log.d(TAG, "Error downloading gps XTRA: ", ioe);
    151         } finally {
    152             if (connection != null) {
    153                 connection.disconnect();
    154             }
    155         }
    156         return null;
    157     }
    158 
    159 }
    160 
    161