Home | History | Annotate | Download | only in research
      1 /*
      2  * Copyright (C) 2012 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.inputmethod.research;
     18 
     19 import android.Manifest;
     20 import android.app.AlarmManager;
     21 import android.app.IntentService;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.content.pm.PackageManager;
     26 import android.net.ConnectivityManager;
     27 import android.net.NetworkInfo;
     28 import android.os.BatteryManager;
     29 import android.os.Bundle;
     30 import android.util.Log;
     31 
     32 import com.android.inputmethod.latin.R;
     33 
     34 import java.io.BufferedReader;
     35 import java.io.File;
     36 import java.io.FileFilter;
     37 import java.io.FileInputStream;
     38 import java.io.IOException;
     39 import java.io.InputStream;
     40 import java.io.InputStreamReader;
     41 import java.io.OutputStream;
     42 import java.net.HttpURLConnection;
     43 import java.net.MalformedURLException;
     44 import java.net.URL;
     45 
     46 public final class UploaderService extends IntentService {
     47     private static final String TAG = UploaderService.class.getSimpleName();
     48     public static final long RUN_INTERVAL = AlarmManager.INTERVAL_HOUR;
     49     private static final String EXTRA_UPLOAD_UNCONDITIONALLY = UploaderService.class.getName()
     50             + ".extra.UPLOAD_UNCONDITIONALLY";
     51     private static final int BUF_SIZE = 1024 * 8;
     52     protected static final int TIMEOUT_IN_MS = 1000 * 4;
     53 
     54     private boolean mCanUpload;
     55     private File mFilesDir;
     56     private URL mUrl;
     57 
     58     public UploaderService() {
     59         super("Research Uploader Service");
     60     }
     61 
     62     @Override
     63     public void onCreate() {
     64         super.onCreate();
     65 
     66         mCanUpload = false;
     67         mFilesDir = null;
     68         mUrl = null;
     69 
     70         final PackageManager packageManager = getPackageManager();
     71         final boolean hasPermission = packageManager.checkPermission(Manifest.permission.INTERNET,
     72                 getPackageName()) == PackageManager.PERMISSION_GRANTED;
     73         if (!hasPermission) {
     74             return;
     75         }
     76 
     77         try {
     78             final String urlString = getString(R.string.research_logger_upload_url);
     79             if (urlString == null || urlString.equals("")) {
     80                 return;
     81             }
     82             mFilesDir = getFilesDir();
     83             mUrl = new URL(urlString);
     84             mCanUpload = true;
     85         } catch (MalformedURLException e) {
     86             e.printStackTrace();
     87         }
     88     }
     89 
     90     @Override
     91     protected void onHandleIntent(Intent intent) {
     92         if (!mCanUpload) {
     93             return;
     94         }
     95         boolean isUploadingUnconditionally = false;
     96         Bundle bundle = intent.getExtras();
     97         if (bundle != null && bundle.containsKey(EXTRA_UPLOAD_UNCONDITIONALLY)) {
     98             isUploadingUnconditionally = bundle.getBoolean(EXTRA_UPLOAD_UNCONDITIONALLY);
     99         }
    100         doUpload(isUploadingUnconditionally);
    101     }
    102 
    103     private boolean isExternallyPowered() {
    104         final Intent intent = registerReceiver(null, new IntentFilter(
    105                 Intent.ACTION_BATTERY_CHANGED));
    106         final int pluggedState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    107         return pluggedState == BatteryManager.BATTERY_PLUGGED_AC
    108                 || pluggedState == BatteryManager.BATTERY_PLUGGED_USB;
    109     }
    110 
    111     private boolean hasWifiConnection() {
    112         final ConnectivityManager manager =
    113                 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    114         final NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    115         return wifiInfo.isConnected();
    116     }
    117 
    118     private void doUpload(final boolean isUploadingUnconditionally) {
    119         if (!isUploadingUnconditionally && (!isExternallyPowered() || !hasWifiConnection())) {
    120             return;
    121         }
    122         if (mFilesDir == null) {
    123             return;
    124         }
    125         final File[] files = mFilesDir.listFiles(new FileFilter() {
    126             @Override
    127             public boolean accept(File pathname) {
    128                 return pathname.getName().startsWith(ResearchLogger.FILENAME_PREFIX)
    129                         && !pathname.canWrite();
    130             }
    131         });
    132         boolean success = true;
    133         if (files.length == 0) {
    134             success = false;
    135         }
    136         for (final File file : files) {
    137             if (!uploadFile(file)) {
    138                 success = false;
    139             }
    140         }
    141     }
    142 
    143     private boolean uploadFile(File file) {
    144         Log.d(TAG, "attempting upload of " + file.getAbsolutePath());
    145         boolean success = false;
    146         final int contentLength = (int) file.length();
    147         HttpURLConnection connection = null;
    148         InputStream fileInputStream = null;
    149         try {
    150             fileInputStream = new FileInputStream(file);
    151             connection = (HttpURLConnection) mUrl.openConnection();
    152             connection.setRequestMethod("PUT");
    153             connection.setDoOutput(true);
    154             connection.setFixedLengthStreamingMode(contentLength);
    155             final OutputStream os = connection.getOutputStream();
    156             final byte[] buf = new byte[BUF_SIZE];
    157             int numBytesRead;
    158             while ((numBytesRead = fileInputStream.read(buf)) != -1) {
    159                 os.write(buf, 0, numBytesRead);
    160             }
    161             if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
    162                 Log.d(TAG, "upload failed: " + connection.getResponseCode());
    163                 InputStream netInputStream = connection.getInputStream();
    164                 BufferedReader reader = new BufferedReader(new InputStreamReader(netInputStream));
    165                 String line;
    166                 while ((line = reader.readLine()) != null) {
    167                     Log.d(TAG, "| " + reader.readLine());
    168                 }
    169                 reader.close();
    170                 return success;
    171             }
    172             file.delete();
    173             success = true;
    174             Log.d(TAG, "upload successful");
    175         } catch (Exception e) {
    176             e.printStackTrace();
    177         } finally {
    178             if (fileInputStream != null) {
    179                 try {
    180                     fileInputStream.close();
    181                 } catch (IOException e) {
    182                     e.printStackTrace();
    183                 }
    184             }
    185             if (connection != null) {
    186                 connection.disconnect();
    187             }
    188         }
    189         return success;
    190     }
    191 }
    192