1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5package org.chromium.chrome.browser.banners; 6 7import android.content.pm.PackageInfo; 8import android.content.pm.PackageManager; 9import android.os.Handler; 10import android.os.Looper; 11import android.os.SystemClock; 12import android.text.TextUtils; 13 14import java.util.List; 15 16/** 17 * Monitors the PackageManager to see when an app has been installed. 18 */ 19public class InstallerDelegate implements Runnable { 20 /** 21 * Callback for when the app install has completed. 22 */ 23 public static interface Observer { 24 /** 25 * Called when the task has finished. 26 * @param delegate Instance of the class that finished. 27 * @param success Whether or not the package was successfully installed. 28 */ 29 public void onInstallFinished(InstallerDelegate delegate, boolean success); 30 } 31 32 private static final long DEFAULT_MS_BETWEEN_RUNS = 1000; 33 private static final long DEFAULT_MS_MAXIMUM_WAITING_TIME = 3 * 60 * 1000; 34 35 /** Message loop to post the Runnable to. */ 36 private final Handler mHandler; 37 38 /** PackageManager that the Runnable is monitoring. */ 39 private final PackageManager mPackageManager; 40 41 /** Object that is notified when the PackageManager has finished. */ 42 private final Observer mObserver; 43 44 /** Name of the package that we need to see the PackageManager has finished installing. */ 45 private final String mPackageName; 46 47 /** Whether or not the Runnable is currently looping. */ 48 private boolean mIsRunning; 49 50 /** Number of milliseconds to wait between calls to run(). */ 51 private long mMsBetweenRuns; 52 53 /** Maximum number of milliseconds to wait before giving up. */ 54 private long mMsMaximumWaitingTime; 55 56 /** Timestamp of when we first started. */ 57 private long mTimestampStarted; 58 59 /** 60 * Constructs the InstallerDelegate. 61 * @param looper Thread to run the Runnable on. 62 * @param packageManager Provides access to the list of installed apps. 63 * @param observer Alerted when the package has been completely installed. 64 * @param packageName Name of the package for the app to monitor. 65 */ 66 InstallerDelegate( 67 Looper looper, PackageManager packageManager, Observer observer, String packageName) { 68 mHandler = new Handler(looper); 69 mPackageManager = packageManager; 70 mObserver = observer; 71 mPackageName = packageName; 72 mMsBetweenRuns = DEFAULT_MS_BETWEEN_RUNS; 73 mMsMaximumWaitingTime = DEFAULT_MS_MAXIMUM_WAITING_TIME; 74 } 75 76 /** 77 * Begin monitoring the PackageManager to see if it completes installing the package. 78 */ 79 public void start() { 80 mTimestampStarted = SystemClock.elapsedRealtime(); 81 mIsRunning = true; 82 mHandler.postDelayed(this, mMsBetweenRuns); 83 } 84 85 /** 86 * Don't call this directly; instead, call {@link #start()}. 87 */ 88 @Override 89 public void run() { 90 boolean isInstalled = isInstalled(); 91 boolean waitedTooLong = 92 (SystemClock.elapsedRealtime() - mTimestampStarted) > mMsMaximumWaitingTime; 93 if (isInstalled || !mIsRunning || waitedTooLong) { 94 mObserver.onInstallFinished(this, isInstalled); 95 mIsRunning = false; 96 } else { 97 mHandler.postDelayed(this, mMsBetweenRuns); 98 } 99 } 100 101 /** 102 * Checks if the app has been installed on the system. 103 * @return True if the PackageManager reports that the app is installed, false otherwise. 104 */ 105 private boolean isInstalled() { 106 List<PackageInfo> packs = mPackageManager.getInstalledPackages(0); 107 for (int i = 0; i < packs.size(); i++) { 108 if (TextUtils.equals(packs.get(i).packageName, mPackageName)) return true; 109 } 110 return false; 111 } 112 113 /** 114 * Prevent rescheduling the Runnable. 115 */ 116 void cancel() { 117 mIsRunning = false; 118 } 119 120 /** 121 * Checks to see if the Runnable will continue scheduling itself. 122 * @return True if the runnable is still being scheduled. 123 */ 124 boolean isRunning() { 125 return mIsRunning; 126 } 127 128 /** 129 * Set how often the handler will check the PackageManager. 130 * @param msBetween How long to wait between executions of the Runnable. 131 * @param msMax How long to wait before giving up. 132 */ 133 void setTimingForTests(long msBetween, long msMax) { 134 mMsBetweenRuns = msBetween; 135 mMsMaximumWaitingTime = msMax; 136 } 137} 138