1/*
2 * Copyright (C) 2010 ZXing authors
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
17package com.google.zxing.client.android;
18
19import android.app.Activity;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24
25import java.util.concurrent.Executors;
26import java.util.concurrent.RejectedExecutionException;
27import java.util.concurrent.ScheduledExecutorService;
28import java.util.concurrent.ScheduledFuture;
29import java.util.concurrent.ThreadFactory;
30import java.util.concurrent.TimeUnit;
31
32/**
33 * Finishes an activity after a period of inactivity if the device is on battery power.
34 */
35final class InactivityTimer {
36
37  private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
38
39  private final ScheduledExecutorService inactivityTimer =
40      Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
41  private final Activity activity;
42  private ScheduledFuture<?> inactivityFuture = null;
43  private final BroadcastReceiver powerStatusReceiver = new PowerStatusReceiver();
44
45  InactivityTimer(Activity activity) {
46    this.activity = activity;
47    onActivity();
48  }
49
50  void onActivity() {
51    cancel();
52    if (!inactivityTimer.isShutdown()) {
53      try {
54        inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
55            INACTIVITY_DELAY_SECONDS,
56            TimeUnit.SECONDS);
57      } catch (RejectedExecutionException ree) {
58        // surprising, but could be normal if for some reason the implementation just doesn't
59        // think it can shcedule again. Since this time-out is non-essential, just forget it
60      }
61    }
62  }
63
64  public void onPause() {
65    cancel();
66    activity.unregisterReceiver(powerStatusReceiver);
67  }
68
69  public void onResume(){
70    activity.registerReceiver(powerStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
71    onActivity();
72  }
73
74  private void cancel() {
75    ScheduledFuture<?> future = inactivityFuture;
76    if (future != null) {
77      future.cancel(true);
78      inactivityFuture = null;
79    }
80  }
81
82  void shutdown() {
83    cancel();
84    inactivityTimer.shutdown();
85  }
86
87  private static final class DaemonThreadFactory implements ThreadFactory {
88    public Thread newThread(Runnable runnable) {
89      Thread thread = new Thread(runnable);
90      thread.setDaemon(true);
91      return thread;
92    }
93  }
94
95  private final class PowerStatusReceiver extends BroadcastReceiver {
96    @Override
97    public void onReceive(Context context, Intent intent){
98      if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
99        // 0 indicates that we're on battery
100        // In Android 2.0+, use BatteryManager.EXTRA_PLUGGED
101        int batteryPlugged = intent.getIntExtra("plugged", -1);
102        if (batteryPlugged > 0) {
103          InactivityTimer.this.cancel();
104        }
105      }
106    }
107  }
108
109}
110