root/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. onInstallFinished
  2. start
  3. run
  4. isInstalled
  5. cancel
  6. isRunning
  7. setTimingForTests

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.banners;

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.text.TextUtils;

import java.util.List;

/**
 * Monitors the PackageManager to see when an app has been installed.
 */
public class InstallerDelegate implements Runnable {
    /**
     * Callback for when the app install has completed.
     */
    public static interface Observer {
        /**
         * Called when the task has finished.
         * @param delegate Instance of the class that finished.
         * @param success  Whether or not the package was successfully installed.
         */
        public void onInstallFinished(InstallerDelegate delegate, boolean success);
    }

    private static final long DEFAULT_MS_BETWEEN_RUNS = 1000;
    private static final long DEFAULT_MS_MAXIMUM_WAITING_TIME = 3 * 60 * 1000;

    /** Message loop to post the Runnable to. */
    private final Handler mHandler;

    /** PackageManager that the Runnable is monitoring. */
    private final PackageManager mPackageManager;

    /** Object that is notified when the PackageManager has finished. */
    private final Observer mObserver;

    /** Name of the package that we need to see the PackageManager has finished installing. */
    private final String mPackageName;

    /** Whether or not the Runnable is currently looping. */
    private boolean mIsRunning;

    /** Number of milliseconds to wait between calls to run(). */
    private long mMsBetweenRuns;

    /** Maximum number of milliseconds to wait before giving up. */
    private long mMsMaximumWaitingTime;

    /** Timestamp of when we first started. */
    private long mTimestampStarted;

    /**
     * Constructs the InstallerDelegate.
     * @param looper         Thread to run the Runnable on.
     * @param packageManager Provides access to the list of installed apps.
     * @param observer       Alerted when the package has been completely installed.
     * @param packageName    Name of the package for the app to monitor.
     */
    InstallerDelegate(
            Looper looper, PackageManager packageManager, Observer observer, String packageName) {
        mHandler = new Handler(looper);
        mPackageManager = packageManager;
        mObserver = observer;
        mPackageName = packageName;
        mMsBetweenRuns = DEFAULT_MS_BETWEEN_RUNS;
        mMsMaximumWaitingTime = DEFAULT_MS_MAXIMUM_WAITING_TIME;
    }

    /**
     * Begin monitoring the PackageManager to see if it completes installing the package.
     */
    public void start() {
        mTimestampStarted = SystemClock.elapsedRealtime();
        mIsRunning = true;
        mHandler.postDelayed(this, mMsBetweenRuns);
    }

    /**
     * Don't call this directly; instead, call {@link #start()}.
     */
    @Override
    public void run() {
        boolean isInstalled = isInstalled();
        boolean waitedTooLong =
                (SystemClock.elapsedRealtime() - mTimestampStarted) > mMsMaximumWaitingTime;
        if (isInstalled || !mIsRunning || waitedTooLong) {
            mObserver.onInstallFinished(this, isInstalled);
            mIsRunning = false;
        } else {
            mHandler.postDelayed(this, mMsBetweenRuns);
        }
    }

    /**
     * Checks if the app has been installed on the system.
     * @return True if the PackageManager reports that the app is installed, false otherwise.
     */
    private boolean isInstalled() {
        List<PackageInfo> packs = mPackageManager.getInstalledPackages(0);
        for (int i = 0; i < packs.size(); i++) {
            if (TextUtils.equals(packs.get(i).packageName, mPackageName)) return true;
        }
        return false;
    }

    /**
     * Prevent rescheduling the Runnable.
     */
    void cancel() {
        mIsRunning = false;
    }

    /**
     * Checks to see if the Runnable will continue scheduling itself.
     * @return True if the runnable is still being scheduled.
     */
    boolean isRunning() {
        return mIsRunning;
    }

    /**
     * Set how often the handler will check the PackageManager.
     * @param msBetween How long to wait between executions of the Runnable.
     * @param msMax     How long to wait before giving up.
     */
    void setTimingForTests(long msBetween, long msMax) {
        mMsBetweenRuns = msBetween;
        mMsMaximumWaitingTime = msMax;
    }
}

/* [<][>][^][v][top][bottom][index][help] */