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