17620644768ffc235607b3a94671e49518c18686fBryan Mawhinney/*
27620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Copyright (C) 2010 ZXing authors
37620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
47620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Licensed under the Apache License, Version 2.0 (the "License");
57620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * you may not use this file except in compliance with the License.
67620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * You may obtain a copy of the License at
77620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
87620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *      http://www.apache.org/licenses/LICENSE-2.0
97620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
107620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Unless required by applicable law or agreed to in writing, software
117620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * distributed under the License is distributed on an "AS IS" BASIS,
127620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * See the License for the specific language governing permissions and
147620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * limitations under the License.
157620644768ffc235607b3a94671e49518c18686fBryan Mawhinney */
167620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
177620644768ffc235607b3a94671e49518c18686fBryan Mawhinneypackage com.google.zxing.client.android;
187620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
197620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.app.Activity;
207620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.content.BroadcastReceiver;
217620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.content.Context;
227620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.content.Intent;
237620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.content.IntentFilter;
247620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
257620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.util.concurrent.Executors;
267620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.util.concurrent.RejectedExecutionException;
277620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.util.concurrent.ScheduledExecutorService;
287620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.util.concurrent.ScheduledFuture;
297620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.util.concurrent.ThreadFactory;
307620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.util.concurrent.TimeUnit;
317620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
327620644768ffc235607b3a94671e49518c18686fBryan Mawhinney/**
337620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Finishes an activity after a period of inactivity if the device is on battery power.
347620644768ffc235607b3a94671e49518c18686fBryan Mawhinney */
357620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyfinal class InactivityTimer {
367620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
377620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
387620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
397620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private final ScheduledExecutorService inactivityTimer =
407620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
417620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private final Activity activity;
427620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private ScheduledFuture<?> inactivityFuture = null;
437620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private final BroadcastReceiver powerStatusReceiver = new PowerStatusReceiver();
447620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
457620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  InactivityTimer(Activity activity) {
467620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    this.activity = activity;
477620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    onActivity();
487620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
497620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
507620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  void onActivity() {
517620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    cancel();
527620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (!inactivityTimer.isShutdown()) {
537620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      try {
547620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
557620644768ffc235607b3a94671e49518c18686fBryan Mawhinney            INACTIVITY_DELAY_SECONDS,
567620644768ffc235607b3a94671e49518c18686fBryan Mawhinney            TimeUnit.SECONDS);
577620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      } catch (RejectedExecutionException ree) {
587620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        // surprising, but could be normal if for some reason the implementation just doesn't
597620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        // think it can shcedule again. Since this time-out is non-essential, just forget it
607620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
617620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
627620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
637620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
647620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void onPause() {
657620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    cancel();
667620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    activity.unregisterReceiver(powerStatusReceiver);
677620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
687620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
697620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  public void onResume(){
707620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    activity.registerReceiver(powerStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
717620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    onActivity();
727620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
737620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
747620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private void cancel() {
757620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    ScheduledFuture<?> future = inactivityFuture;
767620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (future != null) {
777620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      future.cancel(true);
787620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      inactivityFuture = null;
797620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
807620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
817620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
827620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  void shutdown() {
837620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    cancel();
847620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    inactivityTimer.shutdown();
857620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
867620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
877620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static final class DaemonThreadFactory implements ThreadFactory {
887620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    public Thread newThread(Runnable runnable) {
897620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Thread thread = new Thread(runnable);
907620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      thread.setDaemon(true);
917620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      return thread;
927620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
937620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
947620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
957620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private final class PowerStatusReceiver extends BroadcastReceiver {
967620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    @Override
977620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    public void onReceive(Context context, Intent intent){
987620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
997620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        // 0 indicates that we're on battery
1007620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        // In Android 2.0+, use BatteryManager.EXTRA_PLUGGED
1017620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        int batteryPlugged = intent.getIntExtra("plugged", -1);
1027620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        if (batteryPlugged > 0) {
1037620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          InactivityTimer.this.cancel();
1047620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        }
1057620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
1067620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1077620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1087620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1097620644768ffc235607b3a94671e49518c18686fBryan Mawhinney}
110