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 UploaderService()58 public UploaderService() { 59 super("Research Uploader Service"); 60 } 61 62 @Override onCreate()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 onHandleIntent(Intent intent)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 isExternallyPowered()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 hasWifiConnection()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 doUpload(final boolean isUploadingUnconditionally)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 uploadFile(File file)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