19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1700b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwoodpackage com.android.server.location;
1800b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood
1900b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwoodimport android.content.Context;
2000b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwoodimport android.net.Proxy;
2100b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwoodimport android.net.http.AndroidHttpClient;
2200b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwoodimport android.util.Log;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpEntity;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpHost;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.HttpResponse;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.StatusLine;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.client.HttpClient;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.client.methods.HttpGet;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.client.methods.HttpUriRequest;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.http.conn.params.ConnRouteParams;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.DataInputStream;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Properties;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Random;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A class for downloading GPS XTRA data.
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GpsXtraDownloader {
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsXtraDownloader";
46431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato    static final boolean DEBUG = false;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String[] mXtraServers;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // to load balance our server requests
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNextServerIndex;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    GpsXtraDownloader(Context context, Properties properties) {
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // read XTRA servers from the Properties object
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int count = 0;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String server1 = properties.getProperty("XTRA_SERVER_1");
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String server2 = properties.getProperty("XTRA_SERVER_2");
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String server3 = properties.getProperty("XTRA_SERVER_3");
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (server1 != null) count++;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (server2 != null) count++;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (server3 != null) count++;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (count == 0) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "No XTRA servers were specified in the GPS configuration");
677b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project            return;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mXtraServers = new String[count];
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count = 0;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (server1 != null) mXtraServers[count++] = server1;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (server2 != null) mXtraServers[count++] = server2;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (server3 != null) mXtraServers[count++] = server3;
74b8526bfe091d4a5948f6e3165357bb9bd4bfebbfMike Lockwood
75b8526bfe091d4a5948f6e3165357bb9bd4bfebbfMike Lockwood            // randomize first server
76b8526bfe091d4a5948f6e3165357bb9bd4bfebbfMike Lockwood            Random random = new Random();
77b8526bfe091d4a5948f6e3165357bb9bd4bfebbfMike Lockwood            mNextServerIndex = random.nextInt(count);
78b8526bfe091d4a5948f6e3165357bb9bd4bfebbfMike Lockwood        }
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    byte[] downloadXtraData() {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String proxyHost = Proxy.getHost(mContext);
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int proxyPort = Proxy.getPort(mContext);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean useProxy = (proxyHost != null && proxyPort != -1);
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] result = null;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startIndex = mNextServerIndex;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mXtraServers == null) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // load balance our requests among the available servers
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (result == null) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = doDownload(mXtraServers[mNextServerIndex], useProxy, proxyHost, proxyPort);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // increment mNextServerIndex and wrap around if necessary
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextServerIndex++;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNextServerIndex == mXtraServers.length) {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNextServerIndex = 0;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // break if we have tried all the servers
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNextServerIndex == startIndex) break;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected static byte[] doDownload(String url, boolean isProxySet,
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String proxyHost, int proxyPort) {
110431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato        if (DEBUG) Log.d(TAG, "Downloading XTRA data from " + url);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AndroidHttpClient client = null;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = AndroidHttpClient.newInstance("Android");
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HttpUriRequest req = new HttpGet(url);
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isProxySet) {
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                HttpHost proxy = new HttpHost(proxyHost, proxyPort);
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ConnRouteParams.setDefaultProxy(req.getParams(), proxy);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.addHeader(
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Accept",
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic");
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            req.addHeader(
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "x-wap-profile",
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "http://www.openmobilealliance.org/tech/profiles/UAPROF/ccppschema-20021212#");
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HttpResponse response = client.execute(req);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            StatusLine status = response.getStatusLine();
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (status.getStatusCode() != 200) { // HTTP 200 is success.
133431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato                if (DEBUG) Log.d(TAG, "HTTP error: " + status.getReasonPhrase());
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HttpEntity entity = response.getEntity();
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            byte[] body = null;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (entity != null) {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (entity.getContentLength() > 0) {
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        body = new byte[(int) entity.getContentLength()];
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        DataInputStream dis = new DataInputStream(entity.getContent());
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            dis.readFully(body);
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } finally {
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            try {
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                dis.close();
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            } catch (IOException e) {
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.e(TAG, "Unexpected IOException.", e);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } finally {
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (entity != null) {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        entity.consumeContent();
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return body;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
162431bb2269532f2514861b908d5fafda8fa64da79Joe Onorato            if (DEBUG) Log.d(TAG, "error " + e);
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (client != null) {
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                client.close();
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
172