Loading java/src/com/android/inputmethod/research/BootBroadcastReceiver.java +3 −2 Original line number Diff line number Diff line Loading @@ -25,9 +25,10 @@ import android.content.Intent; */ public final class BootBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { public void onReceive(final Context context, final Intent intent) { if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { ResearchLogger.scheduleUploadingService(context); UploaderService.cancelAndRescheduleUploadingService(context, true /* needsRescheduling */); } } } java/src/com/android/inputmethod/research/ResearchLogger.java +2 −29 Original line number Diff line number Diff line Loading @@ -20,16 +20,13 @@ import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOAR import android.accounts.Account; import android.accounts.AccountManager; import android.app.AlarmManager; import android.app.AlertDialog; import android.app.Dialog; import android.app.PendingIntent; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; Loading Loading @@ -74,22 +71,16 @@ import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.research.MotionEventReader.ReplayData; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Random; import java.util.UUID; /** * Logs the use of the LatinIME keyboard. Loading Loading @@ -254,7 +245,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mUploadNowIntent = new Intent(mLatinIME, UploaderService.class); mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { scheduleUploadingService(mLatinIME); UploaderService.cancelAndRescheduleUploadingService(mLatinIME, true /* needsRescheduling */); } mReplayer.setKeyboardSwitcher(keyboardSwitcher); } Loading @@ -268,25 +260,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang ResearchSettings.writeResearchLastDirCleanupTime(mPrefs, now); } /** * Arrange for the UploaderService to be run on a regular basis. * * Any existing scheduled invocation of UploaderService is removed and rescheduled. This may * cause problems if this method is called often and frequent updates are required, but since * the user will likely be sleeping at some point, if the interval is less that the expected * sleep duration and this method is not called during that time, the service should be invoked * at some point. */ public static void scheduleUploadingService(Context context) { final Intent intent = new Intent(context, UploaderService.class); final PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0); final AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); manager.cancel(pendingIntent); manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, UploaderService.RUN_INTERVAL, UploaderService.RUN_INTERVAL, pendingIntent); } public void mainKeyboardView_onAttachedToWindow(final MainKeyboardView mainKeyboardView) { mMainKeyboardView = mainKeyboardView; maybeShowSplashScreen(); Loading java/src/com/android/inputmethod/research/UploaderService.java +46 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.inputmethod.research; import android.app.AlarmManager; import android.app.IntentService; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; Loading @@ -43,11 +45,17 @@ public final class UploaderService extends IntentService { @Override protected void onHandleIntent(final Intent intent) { // We may reach this point either because the alarm fired, or because the system explicitly // requested that an Upload occur. In the latter case, we want to cancel the alarm in case // it's about to fire. cancelAndRescheduleUploadingService(this, false /* needsRescheduling */); final Uploader uploader = new Uploader(this); if (!uploader.isPossibleToUpload()) return; if (isUploadingUnconditionally(intent.getExtras()) || uploader.isConvenientToUpload()) { uploader.doUpload(); } cancelAndRescheduleUploadingService(this, true /* needsRescheduling */); } private boolean isUploadingUnconditionally(final Bundle bundle) { Loading @@ -57,4 +65,42 @@ public final class UploaderService extends IntentService { } return false; } /** * Arrange for the UploaderService to be run on a regular basis. * * Any existing scheduled invocation of UploaderService is removed and optionally rescheduled. * This may cause problems if this method is called so often that no scheduled invocation is * ever run. But if the delay is short enough that it will go off when the user is sleeping, * then there should be no starvation. * * @param context {@link Context} object * @param needsRescheduling whether to schedule a future intent to be delivered to this service */ public static void cancelAndRescheduleUploadingService(final Context context, final boolean needsRescheduling) { final PendingIntent pendingIntent = getPendingIntentForService(context); final AlarmManager alarmManager = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE); cancelAnyScheduledServiceAlarm(alarmManager, pendingIntent); if (needsRescheduling) { scheduleServiceAlarm(alarmManager, pendingIntent); } } private static PendingIntent getPendingIntentForService(final Context context) { final Intent intent = new Intent(context, UploaderService.class); return PendingIntent.getService(context, 0, intent, 0); } private static void cancelAnyScheduledServiceAlarm(final AlarmManager alarmManager, final PendingIntent pendingIntent) { alarmManager.cancel(pendingIntent); } private static void scheduleServiceAlarm(final AlarmManager alarmManager, final PendingIntent pendingIntent) { alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, UploaderService.RUN_INTERVAL, pendingIntent); } } Loading
java/src/com/android/inputmethod/research/BootBroadcastReceiver.java +3 −2 Original line number Diff line number Diff line Loading @@ -25,9 +25,10 @@ import android.content.Intent; */ public final class BootBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { public void onReceive(final Context context, final Intent intent) { if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { ResearchLogger.scheduleUploadingService(context); UploaderService.cancelAndRescheduleUploadingService(context, true /* needsRescheduling */); } } }
java/src/com/android/inputmethod/research/ResearchLogger.java +2 −29 Original line number Diff line number Diff line Loading @@ -20,16 +20,13 @@ import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOAR import android.accounts.Account; import android.accounts.AccountManager; import android.app.AlarmManager; import android.app.AlertDialog; import android.app.Dialog; import android.app.PendingIntent; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; Loading Loading @@ -74,22 +71,16 @@ import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.research.MotionEventReader.ReplayData; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Random; import java.util.UUID; /** * Logs the use of the LatinIME keyboard. Loading Loading @@ -254,7 +245,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mUploadNowIntent = new Intent(mLatinIME, UploaderService.class); mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { scheduleUploadingService(mLatinIME); UploaderService.cancelAndRescheduleUploadingService(mLatinIME, true /* needsRescheduling */); } mReplayer.setKeyboardSwitcher(keyboardSwitcher); } Loading @@ -268,25 +260,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang ResearchSettings.writeResearchLastDirCleanupTime(mPrefs, now); } /** * Arrange for the UploaderService to be run on a regular basis. * * Any existing scheduled invocation of UploaderService is removed and rescheduled. This may * cause problems if this method is called often and frequent updates are required, but since * the user will likely be sleeping at some point, if the interval is less that the expected * sleep duration and this method is not called during that time, the service should be invoked * at some point. */ public static void scheduleUploadingService(Context context) { final Intent intent = new Intent(context, UploaderService.class); final PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0); final AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); manager.cancel(pendingIntent); manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, UploaderService.RUN_INTERVAL, UploaderService.RUN_INTERVAL, pendingIntent); } public void mainKeyboardView_onAttachedToWindow(final MainKeyboardView mainKeyboardView) { mMainKeyboardView = mainKeyboardView; maybeShowSplashScreen(); Loading
java/src/com/android/inputmethod/research/UploaderService.java +46 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.inputmethod.research; import android.app.AlarmManager; import android.app.IntentService; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; Loading @@ -43,11 +45,17 @@ public final class UploaderService extends IntentService { @Override protected void onHandleIntent(final Intent intent) { // We may reach this point either because the alarm fired, or because the system explicitly // requested that an Upload occur. In the latter case, we want to cancel the alarm in case // it's about to fire. cancelAndRescheduleUploadingService(this, false /* needsRescheduling */); final Uploader uploader = new Uploader(this); if (!uploader.isPossibleToUpload()) return; if (isUploadingUnconditionally(intent.getExtras()) || uploader.isConvenientToUpload()) { uploader.doUpload(); } cancelAndRescheduleUploadingService(this, true /* needsRescheduling */); } private boolean isUploadingUnconditionally(final Bundle bundle) { Loading @@ -57,4 +65,42 @@ public final class UploaderService extends IntentService { } return false; } /** * Arrange for the UploaderService to be run on a regular basis. * * Any existing scheduled invocation of UploaderService is removed and optionally rescheduled. * This may cause problems if this method is called so often that no scheduled invocation is * ever run. But if the delay is short enough that it will go off when the user is sleeping, * then there should be no starvation. * * @param context {@link Context} object * @param needsRescheduling whether to schedule a future intent to be delivered to this service */ public static void cancelAndRescheduleUploadingService(final Context context, final boolean needsRescheduling) { final PendingIntent pendingIntent = getPendingIntentForService(context); final AlarmManager alarmManager = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE); cancelAnyScheduledServiceAlarm(alarmManager, pendingIntent); if (needsRescheduling) { scheduleServiceAlarm(alarmManager, pendingIntent); } } private static PendingIntent getPendingIntentForService(final Context context) { final Intent intent = new Intent(context, UploaderService.class); return PendingIntent.getService(context, 0, intent, 0); } private static void cancelAnyScheduledServiceAlarm(final AlarmManager alarmManager, final PendingIntent pendingIntent) { alarmManager.cancel(pendingIntent); } private static void scheduleServiceAlarm(final AlarmManager alarmManager, final PendingIntent pendingIntent) { alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, UploaderService.RUN_INTERVAL, pendingIntent); } }