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