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.content.Context; 20 import android.net.Proxy; 21 import android.net.http.AndroidHttpClient; 22 import android.text.TextUtils; 23 import android.util.Log; 24 25 import org.apache.http.HttpEntity; 26 import org.apache.http.HttpHost; 27 import org.apache.http.HttpResponse; 28 import org.apache.http.StatusLine; 29 import org.apache.http.client.methods.HttpGet; 30 import org.apache.http.client.methods.HttpUriRequest; 31 import org.apache.http.conn.params.ConnRouteParams; 32 33 import java.io.DataInputStream; 34 import java.io.IOException; 35 import java.util.Properties; 36 import java.util.Random; 37 38 /** 39 * A class for downloading GPS XTRA data. 40 * 41 * {@hide} 42 */ 43 public class GpsXtraDownloader { 44 45 private static final String TAG = "GpsXtraDownloader"; 46 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 47 private static final String DEFAULT_USER_AGENT = "Android"; 48 49 private final Context mContext; 50 private final String[] mXtraServers; 51 // to load balance our server requests 52 private int mNextServerIndex; 53 private final String mUserAgent; 54 55 GpsXtraDownloader(Context context, Properties properties) { 56 mContext = context; 57 58 // read XTRA servers from the Properties object 59 int count = 0; 60 String server1 = properties.getProperty("XTRA_SERVER_1"); 61 String server2 = properties.getProperty("XTRA_SERVER_2"); 62 String server3 = properties.getProperty("XTRA_SERVER_3"); 63 if (server1 != null) count++; 64 if (server2 != null) count++; 65 if (server3 != null) count++; 66 67 // Set User Agent from properties, if possible. 68 String agent = properties.getProperty("XTRA_USER_AGENT"); 69 if (TextUtils.isEmpty(agent)) { 70 mUserAgent = DEFAULT_USER_AGENT; 71 } else { 72 mUserAgent = agent; 73 } 74 75 if (count == 0) { 76 Log.e(TAG, "No XTRA servers were specified in the GPS configuration"); 77 mXtraServers = null; 78 return; 79 } else { 80 mXtraServers = new String[count]; 81 count = 0; 82 if (server1 != null) mXtraServers[count++] = server1; 83 if (server2 != null) mXtraServers[count++] = server2; 84 if (server3 != null) mXtraServers[count++] = server3; 85 86 // randomize first server 87 Random random = new Random(); 88 mNextServerIndex = random.nextInt(count); 89 } 90 } 91 92 byte[] downloadXtraData() { 93 String proxyHost = Proxy.getHost(mContext); 94 int proxyPort = Proxy.getPort(mContext); 95 boolean useProxy = (proxyHost != null && proxyPort != -1); 96 byte[] result = null; 97 int startIndex = mNextServerIndex; 98 99 if (mXtraServers == null) { 100 return null; 101 } 102 103 // load balance our requests among the available servers 104 while (result == null) { 105 result = doDownload(mXtraServers[mNextServerIndex], useProxy, proxyHost, proxyPort); 106 107 // increment mNextServerIndex and wrap around if necessary 108 mNextServerIndex++; 109 if (mNextServerIndex == mXtraServers.length) { 110 mNextServerIndex = 0; 111 } 112 // break if we have tried all the servers 113 if (mNextServerIndex == startIndex) break; 114 } 115 116 return result; 117 } 118 119 protected byte[] doDownload(String url, boolean isProxySet, 120 String proxyHost, int proxyPort) { 121 if (DEBUG) Log.d(TAG, "Downloading XTRA data from " + url); 122 123 AndroidHttpClient client = null; 124 try { 125 if (DEBUG) Log.d(TAG, "XTRA user agent: " + mUserAgent); 126 client = AndroidHttpClient.newInstance(mUserAgent); 127 HttpUriRequest req = new HttpGet(url); 128 129 if (isProxySet) { 130 HttpHost proxy = new HttpHost(proxyHost, proxyPort); 131 ConnRouteParams.setDefaultProxy(req.getParams(), proxy); 132 } 133 134 req.addHeader( 135 "Accept", 136 "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic"); 137 138 req.addHeader( 139 "x-wap-profile", 140 "http://www.openmobilealliance.org/tech/profiles/UAPROF/ccppschema-20021212#"); 141 142 HttpResponse response = client.execute(req); 143 StatusLine status = response.getStatusLine(); 144 if (status.getStatusCode() != 200) { // HTTP 200 is success. 145 if (DEBUG) Log.d(TAG, "HTTP error: " + status.getReasonPhrase()); 146 return null; 147 } 148 149 HttpEntity entity = response.getEntity(); 150 byte[] body = null; 151 if (entity != null) { 152 try { 153 if (entity.getContentLength() > 0) { 154 body = new byte[(int) entity.getContentLength()]; 155 DataInputStream dis = new DataInputStream(entity.getContent()); 156 try { 157 dis.readFully(body); 158 } finally { 159 try { 160 dis.close(); 161 } catch (IOException e) { 162 Log.e(TAG, "Unexpected IOException.", e); 163 } 164 } 165 } 166 } finally { 167 if (entity != null) { 168 entity.consumeContent(); 169 } 170 } 171 } 172 return body; 173 } catch (Exception e) { 174 if (DEBUG) Log.d(TAG, "error " + e); 175 } finally { 176 if (client != null) { 177 client.close(); 178 } 179 } 180 return null; 181 } 182 183 } 184