• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_AUTO_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 
Uploader(final Context context)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 
isPossibleToUpload()78     public boolean isPossibleToUpload() {
79         return hasUploadingPermission() && mUrl != null && !IS_INHIBITING_AUTO_UPLOAD;
80     }
81 
hasUploadingPermission()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 
isConvenientToUpload()88     public boolean isConvenientToUpload() {
89         return isExternallyPowered() && hasWifiConnection();
90     }
91 
isExternallyPowered()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 
hasWifiConnection()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 
doUpload()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 
uploadFile(final File file)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 
uploadContents(final InputStream is, final OutputStream os)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