UploaderService.java revision 9283644c41bf702217168a1750aa82954a4f3f47
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 if (isUploadingUnconditionally(intent.getExtras()) || isConvenientToUpload()) { 103 doUpload(); 104 } 105 } 106 107 private boolean isUploadingUnconditionally(final Bundle bundle) { 108 if (bundle == null) return false; 109 if (bundle.containsKey(EXTRA_UPLOAD_UNCONDITIONALLY)) { 110 return bundle.getBoolean(EXTRA_UPLOAD_UNCONDITIONALLY); 111 } 112 return false; 113 } 114 115 private boolean isConvenientToUpload() { 116 return isExternallyPowered() && hasWifiConnection(); 117 } 118 119 private boolean isExternallyPowered() { 120 final Intent intent = registerReceiver(null, new IntentFilter( 121 Intent.ACTION_BATTERY_CHANGED)); 122 final int pluggedState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); 123 return pluggedState == BatteryManager.BATTERY_PLUGGED_AC 124 || pluggedState == BatteryManager.BATTERY_PLUGGED_USB; 125 } 126 127 private boolean hasWifiConnection() { 128 final ConnectivityManager manager = 129 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 130 final NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 131 return wifiInfo.isConnected(); 132 } 133 134 private void doUpload() { 135 if (mFilesDir == null) { 136 return; 137 } 138 final File[] files = mFilesDir.listFiles(new FileFilter() { 139 @Override 140 public boolean accept(File pathname) { 141 return pathname.getName().startsWith(ResearchLogger.LOG_FILENAME_PREFIX) 142 && !pathname.canWrite(); 143 } 144 }); 145 boolean success = true; 146 if (files.length == 0) { 147 success = false; 148 } 149 for (final File file : files) { 150 if (!uploadFile(file)) { 151 success = false; 152 } 153 } 154 } 155 156 private boolean uploadFile(File file) { 157 if (DEBUG) { 158 Log.d(TAG, "attempting upload of " + file.getAbsolutePath()); 159 } 160 boolean success = false; 161 final int contentLength = (int) file.length(); 162 HttpURLConnection connection = null; 163 InputStream fileInputStream = null; 164 try { 165 fileInputStream = new FileInputStream(file); 166 connection = (HttpURLConnection) mUrl.openConnection(); 167 connection.setRequestMethod("PUT"); 168 connection.setDoOutput(true); 169 connection.setFixedLengthStreamingMode(contentLength); 170 final OutputStream os = connection.getOutputStream(); 171 final byte[] buf = new byte[BUF_SIZE]; 172 int numBytesRead; 173 while ((numBytesRead = fileInputStream.read(buf)) != -1) { 174 os.write(buf, 0, numBytesRead); 175 if (DEBUG) { 176 Log.d(TAG, new String(buf)); 177 } 178 } 179 if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { 180 Log.d(TAG, "upload failed: " + connection.getResponseCode()); 181 InputStream netInputStream = connection.getInputStream(); 182 BufferedReader reader = new BufferedReader(new InputStreamReader(netInputStream)); 183 String line; 184 while ((line = reader.readLine()) != null) { 185 Log.d(TAG, "| " + reader.readLine()); 186 } 187 reader.close(); 188 return success; 189 } 190 file.delete(); 191 success = true; 192 if (DEBUG) { 193 Log.d(TAG, "upload successful"); 194 } 195 } catch (Exception e) { 196 e.printStackTrace(); 197 } finally { 198 if (fileInputStream != null) { 199 try { 200 fileInputStream.close(); 201 } catch (IOException e) { 202 e.printStackTrace(); 203 } 204 } 205 if (connection != null) { 206 connection.disconnect(); 207 } 208 } 209 return success; 210 } 211} 212