Home | History | Annotate | Download | only in research
      1 /*
      2  * Copyright (C) 2013 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.inputmethod.research;
     18 
     19 import android.Manifest;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.content.pm.PackageManager;
     24 import android.net.ConnectivityManager;
     25 import android.net.NetworkInfo;
     26 import android.os.BatteryManager;
     27 import android.text.TextUtils;
     28 import android.util.Log;
     29 
     30 import com.android.inputmethod.latin.R;
     31 import com.android.inputmethod.latin.define.ProductionFlag;
     32 
     33 import java.io.BufferedReader;
     34 import java.io.File;
     35 import java.io.FileInputStream;
     36 import java.io.IOException;
     37 import java.io.InputStream;
     38 import java.io.InputStreamReader;
     39 import java.io.OutputStream;
     40 import java.net.HttpURLConnection;
     41 import java.net.MalformedURLException;
     42 import java.net.URL;
     43 
     44 /**
     45  * Manages the uploading of ResearchLog files.
     46  */
     47 public final class Uploader {
     48     private static final String TAG = Uploader.class.getSimpleName();
     49     private static final boolean DEBUG = false
     50             && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
     51     // Set IS_INHIBITING_AUTO_UPLOAD to true for local testing
     52     private static final boolean IS_INHIBITING_UPLOAD = false
     53             && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
     54     private static final int BUF_SIZE = 1024 * 8;
     55 
     56     private final Context mContext;
     57     private final ResearchLogDirectory mResearchLogDirectory;
     58     private final URL mUrl;
     59 
     60     public Uploader(final Context context) {
     61         mContext = context;
     62         mResearchLogDirectory = new ResearchLogDirectory(context);
     63 
     64         final String urlString = context.getString(R.string.research_logger_upload_url);
     65         if (TextUtils.isEmpty(urlString)) {
     66             mUrl = null;
     67             return;
     68         }
     69         URL url = null;
     70         try {
     71             url = new URL(urlString);
     72         } catch (final MalformedURLException e) {
     73             Log.e(TAG, "Bad URL for uploading", e);
     74         }
     75         mUrl = url;
     76     }
     77 
     78     public boolean isPossibleToUpload() {
     79         return hasUploadingPermission() && mUrl != null && !IS_INHIBITING_UPLOAD;
     80     }
     81 
     82     private boolean hasUploadingPermission() {
     83         final PackageManager packageManager = mContext.getPackageManager();
     84         return packageManager.checkPermission(Manifest.permission.INTERNET,
     85                 mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED;
     86     }
     87 
     88     public boolean isConvenientToUpload() {
     89         return isExternallyPowered() && hasWifiConnection();
     90     }
     91 
     92     private boolean isExternallyPowered() {
     93         final Intent intent = mContext.registerReceiver(null, new IntentFilter(
     94                 Intent.ACTION_BATTERY_CHANGED));
     95         final int pluggedState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
     96         return pluggedState == BatteryManager.BATTERY_PLUGGED_AC
     97                 || pluggedState == BatteryManager.BATTERY_PLUGGED_USB;
     98     }
     99 
    100     private boolean hasWifiConnection() {
    101         final ConnectivityManager manager =
    102                 (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
    103         final NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    104         return wifiInfo.isConnected();
    105     }
    106 
    107     public void doUpload() {
    108         final File[] files = mResearchLogDirectory.getUploadableLogFiles();
    109         if (files == null) return;
    110         for (final File file : files) {
    111             uploadFile(file);
    112         }
    113     }
    114 
    115     private void uploadFile(final File file) {
    116         if (DEBUG) {
    117             Log.d(TAG, "attempting upload of " + file.getAbsolutePath());
    118         }
    119         final int contentLength = (int) file.length();
    120         HttpURLConnection connection = null;
    121         InputStream fileInputStream = null;
    122         try {
    123             fileInputStream = new FileInputStream(file);
    124             connection = (HttpURLConnection) mUrl.openConnection();
    125             connection.setRequestMethod("PUT");
    126             connection.setDoOutput(true);
    127             connection.setFixedLengthStreamingMode(contentLength);
    128             final OutputStream outputStream = connection.getOutputStream();
    129             uploadContents(fileInputStream, outputStream);
    130             if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
    131                 Log.d(TAG, "upload failed: " + connection.getResponseCode());
    132                 final InputStream netInputStream = connection.getInputStream();
    133                 final BufferedReader reader = new BufferedReader(new InputStreamReader(
    134                         netInputStream));
    135                 String line;
    136                 while ((line = reader.readLine()) != null) {
    137                     Log.d(TAG, "| " + reader.readLine());
    138                 }
    139                 reader.close();
    140                 return;
    141             }
    142             file.delete();
    143             if (DEBUG) {
    144                 Log.d(TAG, "upload successful");
    145             }
    146         } catch (final IOException e) {
    147             Log.e(TAG, "Exception uploading file", e);
    148         } finally {
    149             if (fileInputStream != null) {
    150                 try {
    151                     fileInputStream.close();
    152                 } catch (final IOException e) {
    153                     Log.e(TAG, "Exception closing uploaded file", e);
    154                 }
    155             }
    156             if (connection != null) {
    157                 connection.disconnect();
    158             }
    159         }
    160     }
    161 
    162     private static void uploadContents(final InputStream is, final OutputStream os)
    163             throws IOException {
    164         // TODO: Switch to NIO.
    165         final byte[] buf = new byte[BUF_SIZE];
    166         int numBytesRead;
    167         while ((numBytesRead = is.read(buf)) != -1) {
    168             os.write(buf, 0, numBytesRead);
    169         }
    170     }
    171 }
    172