blob: ba05ec12b07bee643bca282670885a5c25229a5e [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.research;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.BatteryManager;
import android.text.TextUtils;
import android.util.Log;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.define.ProductionFlag;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Manages the uploading of ResearchLog files.
*/
public final class Uploader {
private static final String TAG = Uploader.class.getSimpleName();
private static final boolean DEBUG = false
&& ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
// Set IS_INHIBITING_AUTO_UPLOAD to true for local testing
private static final boolean IS_INHIBITING_AUTO_UPLOAD = false
&& ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
private static final int BUF_SIZE = 1024 * 8;
private final Context mContext;
private final ResearchLogDirectory mResearchLogDirectory;
private final URL mUrl;
public Uploader(final Context context) {
mContext = context;
mResearchLogDirectory = new ResearchLogDirectory(context);
final String urlString = context.getString(R.string.research_logger_upload_url);
if (TextUtils.isEmpty(urlString)) {
mUrl = null;
return;
}
URL url = null;
try {
url = new URL(urlString);
} catch (final MalformedURLException e) {
Log.e(TAG, "Bad URL for uploading", e);
}
mUrl = url;
}
public boolean isPossibleToUpload() {
return hasUploadingPermission() && mUrl != null && !IS_INHIBITING_AUTO_UPLOAD;
}
private boolean hasUploadingPermission() {
final PackageManager packageManager = mContext.getPackageManager();
return packageManager.checkPermission(Manifest.permission.INTERNET,
mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED;
}
public boolean isConvenientToUpload() {
return isExternallyPowered() && hasWifiConnection();
}
private boolean isExternallyPowered() {
final Intent intent = mContext.registerReceiver(null, new IntentFilter(
Intent.ACTION_BATTERY_CHANGED));
final int pluggedState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
return pluggedState == BatteryManager.BATTERY_PLUGGED_AC
|| pluggedState == BatteryManager.BATTERY_PLUGGED_USB;
}
private boolean hasWifiConnection() {
final ConnectivityManager manager =
(ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return wifiInfo.isConnected();
}
public void doUpload() {
final File[] files = mResearchLogDirectory.getUploadableLogFiles();
if (files == null) return;
for (final File file : files) {
uploadFile(file);
}
}
private void uploadFile(final File file) {
if (DEBUG) {
Log.d(TAG, "attempting upload of " + file.getAbsolutePath());
}
final int contentLength = (int) file.length();
HttpURLConnection connection = null;
InputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
connection = (HttpURLConnection) mUrl.openConnection();
connection.setRequestMethod("PUT");
connection.setDoOutput(true);
connection.setFixedLengthStreamingMode(contentLength);
final OutputStream outputStream = connection.getOutputStream();
uploadContents(fileInputStream, outputStream);
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
Log.d(TAG, "upload failed: " + connection.getResponseCode());
final InputStream netInputStream = connection.getInputStream();
final BufferedReader reader = new BufferedReader(new InputStreamReader(
netInputStream));
String line;
while ((line = reader.readLine()) != null) {
Log.d(TAG, "| " + reader.readLine());
}
reader.close();
return;
}
file.delete();
if (DEBUG) {
Log.d(TAG, "upload successful");
}
} catch (final IOException e) {
Log.e(TAG, "Exception uploading file", e);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (final IOException e) {
Log.e(TAG, "Exception closing uploaded file", e);
}
}
if (connection != null) {
connection.disconnect();
}
}
}
private static void uploadContents(final InputStream is, final OutputStream os)
throws IOException {
// TODO: Switch to NIO.
final byte[] buf = new byte[BUF_SIZE];
int numBytesRead;
while ((numBytesRead = is.read(buf)) != -1) {
os.write(buf, 0, numBytesRead);
}
}
}