/*
**
** Copyright 2013, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package com.android.packageinstaller;

import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.EventLog;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import libcore.io.IoUtils;

/**
 * Analytics about an attempt to install a package via {@link PackageInstallerActivity}.
 *
 * <p>An instance of this class is created at the beginning of the install flow and gradually filled
 * as the user progresses through the flow. When the flow terminates (regardless of the reason),
 * {@link #setFlowFinished(byte)} is invoked which reports the installation attempt as an event
 * to the Event Log.
 */
public class InstallFlowAnalytics implements Parcelable {

    private static final String TAG = "InstallFlowAnalytics";

    /** Installation has not yet terminated. */
    static final byte RESULT_NOT_YET_AVAILABLE = -1;

    /** Package successfully installed. */
    static final byte RESULT_SUCCESS = 0;

    /** Installation failed because scheme unsupported. */
    static final byte RESULT_FAILED_UNSUPPORTED_SCHEME = 1;

    /**
     * Installation of an APK failed because of a failure to obtain information from the provided
     * APK.
     */
    static final byte RESULT_FAILED_TO_GET_PACKAGE_INFO = 2;

    /**
     * Installation of an already installed package into the current user profile failed because the
     * specified package is not installed.
     */
    static final byte RESULT_FAILED_PACKAGE_MISSING = 3;

    /**
     * Installation failed because installation from unknown sources is prohibited by the Unknown
     * Sources setting.
     */
    static final byte RESULT_BLOCKED_BY_UNKNOWN_SOURCES_SETTING = 4;

    /** Installation cancelled by the user. */
    static final byte RESULT_CANCELLED_BY_USER = 5;

    /**
     * Installation failed due to {@code PackageManager} failure. PackageManager error code is
     * provided in {@link #mPackageManagerInstallResult}).
     */
    static final byte RESULT_PACKAGE_MANAGER_INSTALL_FAILED = 6;

    private static final int FLAG_INSTALLS_FROM_UNKNOWN_SOURCES_PERMITTED = 1 << 0;
    private static final int FLAG_INSTALL_REQUEST_FROM_UNKNOWN_SOURCE = 1 << 1;
    private static final int FLAG_VERIFY_APPS_ENABLED = 1 << 2;
    private static final int FLAG_APP_VERIFIER_INSTALLED = 1 << 3;
    private static final int FLAG_FILE_URI = 1 << 4;
    private static final int FLAG_REPLACE = 1 << 5;
    private static final int FLAG_SYSTEM_APP = 1 << 6;
    private static final int FLAG_PACKAGE_INFO_OBTAINED = 1 << 7;
    private static final int FLAG_INSTALL_BUTTON_CLICKED = 1 << 8;
    private static final int FLAG_NEW_PERMISSIONS_FOUND = 1 << 9;
    private static final int FLAG_PERMISSIONS_DISPLAYED = 1 << 10;
    private static final int FLAG_NEW_PERMISSIONS_DISPLAYED = 1 << 11;
    private static final int FLAG_ALL_PERMISSIONS_DISPLAYED = 1 << 12;

    /**
     * Information about this flow expressed as a collection of flags. See {@code FLAG_...}
     * constants.
     */
    private int mFlags;

    /** Outcome of the flow. See {@code RESULT_...} constants. */
    private byte mResult = RESULT_NOT_YET_AVAILABLE;

    /**
     * Result code returned by {@code PackageManager} to install the package or {@code 0} if
     * {@code PackageManager} has not yet been invoked to install the package.
     */
    private int mPackageManagerInstallResult;

    /**
     * Time instant when the installation request arrived, measured in elapsed realtime
     * milliseconds. See {@link SystemClock#elapsedRealtime()}.
     */
    private long mStartTimestampMillis;

    /**
     * Time instant when the information about the package being installed was obtained, measured in
     * elapsed realtime milliseconds. See {@link SystemClock#elapsedRealtime()}.
     */
    private long mPackageInfoObtainedTimestampMillis;

    /**
     * Time instant when the user clicked the Install button, measured in elapsed realtime
     * milliseconds. See {@link SystemClock#elapsedRealtime()}. This field is only valid if the
     * Install button has been clicked, as signaled by {@link #FLAG_INSTALL_BUTTON_CLICKED}.
     */
    private long mInstallButtonClickTimestampMillis;

    /**
     * Time instant when this flow terminated, measured in elapsed realtime milliseconds. See
     * {@link SystemClock#elapsedRealtime()}.
     */
    private long mEndTimestampMillis;

    /** URI of the package being installed. */
    private String mPackageUri;

    /** Whether this attempt has been logged to the Event Log. */
    private boolean mLogged;

    private Context mContext;

    public static final Parcelable.Creator<InstallFlowAnalytics> CREATOR =
            new Parcelable.Creator<InstallFlowAnalytics>() {
        @Override
        public InstallFlowAnalytics createFromParcel(Parcel in) {
            return new InstallFlowAnalytics(in);
        }

        @Override
        public InstallFlowAnalytics[] newArray(int size) {
            return new InstallFlowAnalytics[size];
        }
    };

    public InstallFlowAnalytics() {}

    public InstallFlowAnalytics(Parcel in) {
        mFlags = in.readInt();
        mResult = in.readByte();
        mPackageManagerInstallResult = in.readInt();
        mStartTimestampMillis = in.readLong();
        mPackageInfoObtainedTimestampMillis = in.readLong();
        mInstallButtonClickTimestampMillis = in.readLong();
        mEndTimestampMillis = in.readLong();
        mPackageUri = in.readString();
        mLogged = readBoolean(in);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mFlags);
        dest.writeByte(mResult);
        dest.writeInt(mPackageManagerInstallResult);
        dest.writeLong(mStartTimestampMillis);
        dest.writeLong(mPackageInfoObtainedTimestampMillis);
        dest.writeLong(mInstallButtonClickTimestampMillis);
        dest.writeLong(mEndTimestampMillis);
        dest.writeString(mPackageUri);
        writeBoolean(dest, mLogged);
    }

    private static void writeBoolean(Parcel dest, boolean value) {
        dest.writeByte((byte) (value ? 1 : 0));
    }

    private static boolean readBoolean(Parcel dest) {
        return dest.readByte() != 0;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    void setContext(Context context) {
        mContext = context;
    }

    /** Sets whether the Unknown Sources setting is checked. */
    void setInstallsFromUnknownSourcesPermitted(boolean permitted) {
        setFlagState(FLAG_INSTALLS_FROM_UNKNOWN_SOURCES_PERMITTED, permitted);
    }

    /** Gets whether the Unknown Sources setting is checked. */
    private boolean isInstallsFromUnknownSourcesPermitted() {
        return isFlagSet(FLAG_INSTALLS_FROM_UNKNOWN_SOURCES_PERMITTED);
    }

    /** Sets whether this install attempt is from an unknown source. */
    void setInstallRequestFromUnknownSource(boolean unknownSource) {
        setFlagState(FLAG_INSTALL_REQUEST_FROM_UNKNOWN_SOURCE, unknownSource);
    }

    /** Gets whether this install attempt is from an unknown source. */
    private boolean isInstallRequestFromUnknownSource() {
        return isFlagSet(FLAG_INSTALL_REQUEST_FROM_UNKNOWN_SOURCE);
    }

    /** Sets whether app verification is enabled. */
    void setVerifyAppsEnabled(boolean enabled) {
        setFlagState(FLAG_VERIFY_APPS_ENABLED, enabled);
    }

    /** Gets whether app verification is enabled. */
    private boolean isVerifyAppsEnabled() {
        return isFlagSet(FLAG_VERIFY_APPS_ENABLED);
    }

    /** Sets whether at least one app verifier is installed. */
    void setAppVerifierInstalled(boolean installed) {
        setFlagState(FLAG_APP_VERIFIER_INSTALLED, installed);
    }

    /** Gets whether at least one app verifier is installed. */
    private boolean isAppVerifierInstalled() {
        return isFlagSet(FLAG_APP_VERIFIER_INSTALLED);
    }

    /**
     * Sets whether an APK file is being installed.
     *
     * @param fileUri {@code true} if an APK file is being installed, {@code false} if an already
     *        installed package is being installed to this user profile.
     */
    void setFileUri(boolean fileUri) {
        setFlagState(FLAG_FILE_URI, fileUri);
    }

    /**
     * Sets the URI of the package being installed.
     */
    void setPackageUri(String packageUri) {
        mPackageUri = packageUri;
    }

    /**
     * Gets whether an APK file is being installed.
     *
     * @return {@code true} if an APK file is being installed, {@code false} if an already
     *         installed package is being installed to this user profile.
     */
    private boolean isFileUri() {
        return isFlagSet(FLAG_FILE_URI);
    }

    /** Sets whether this is an attempt to replace an existing package. */
    void setReplace(boolean replace) {
        setFlagState(FLAG_REPLACE, replace);
    }

    /** Gets whether this is an attempt to replace an existing package. */
    private boolean isReplace() {
        return isFlagSet(FLAG_REPLACE);
    }

    /** Sets whether the package being updated is a system package. */
    void setSystemApp(boolean systemApp) {
        setFlagState(FLAG_SYSTEM_APP, systemApp);
    }

    /** Gets whether the package being updated is a system package. */
    private boolean isSystemApp() {
        return isFlagSet(FLAG_SYSTEM_APP);
    }

    /**
     * Sets whether the package being installed is requesting more permissions than the already
     * installed version of the package.
     */
    void setNewPermissionsFound(boolean found) {
        setFlagState(FLAG_NEW_PERMISSIONS_FOUND, found);
    }

    /**
     * Gets whether the package being installed is requesting more permissions than the already
     * installed version of the package.
     */
    private boolean isNewPermissionsFound() {
        return isFlagSet(FLAG_NEW_PERMISSIONS_FOUND);
    }

    /** Sets whether permissions were displayed to the user. */
    void setPermissionsDisplayed(boolean displayed) {
        setFlagState(FLAG_PERMISSIONS_DISPLAYED, displayed);
    }

    /** Gets whether permissions were displayed to the user. */
    private boolean isPermissionsDisplayed() {
        return isFlagSet(FLAG_PERMISSIONS_DISPLAYED);
    }

    /**
     * Sets whether new permissions were displayed to the user (if permissions were displayed at
     * all).
     */
    void setNewPermissionsDisplayed(boolean displayed) {
        setFlagState(FLAG_NEW_PERMISSIONS_DISPLAYED, displayed);
    }

    /**
     * Gets whether new permissions were displayed to the user (if permissions were displayed at
     * all).
     */
    private boolean isNewPermissionsDisplayed() {
        return isFlagSet(FLAG_NEW_PERMISSIONS_DISPLAYED);
    }

    /**
     * Sets whether all permissions were displayed to the user (if permissions were displayed at
     * all).
     */
    void setAllPermissionsDisplayed(boolean displayed) {
        setFlagState(FLAG_ALL_PERMISSIONS_DISPLAYED, displayed);
    }

    /**
     * Gets whether all permissions were displayed to the user (if permissions were displayed at
     * all).
     */
    private boolean isAllPermissionsDisplayed() {
        return isFlagSet(FLAG_ALL_PERMISSIONS_DISPLAYED);
    }

    /**
     * Sets the time instant when the installation request arrived, measured in elapsed realtime
     * milliseconds. See {@link SystemClock#elapsedRealtime()}.
     */
    void setStartTimestampMillis(long timestampMillis) {
        mStartTimestampMillis = timestampMillis;
    }

    /**
     * Records that the information about the package info has been obtained or that there has been
     * a failure to obtain the information.
     */
    void setPackageInfoObtained() {
        setFlagState(FLAG_PACKAGE_INFO_OBTAINED, true);
        mPackageInfoObtainedTimestampMillis = SystemClock.elapsedRealtime();
    }

    /**
     * Checks whether the information about the package info has been obtained or that there has
     * been a failure to obtain the information.
     */
    private boolean isPackageInfoObtained() {
        return isFlagSet(FLAG_PACKAGE_INFO_OBTAINED);
    }

    /**
     * Records that the Install button has been clicked.
     */
    void setInstallButtonClicked() {
        setFlagState(FLAG_INSTALL_BUTTON_CLICKED, true);
        mInstallButtonClickTimestampMillis = SystemClock.elapsedRealtime();
    }

    /**
     * Checks whether the Install button has been clicked.
     */
    private boolean isInstallButtonClicked() {
        return isFlagSet(FLAG_INSTALL_BUTTON_CLICKED);
    }

    /**
     * Marks this flow as finished due to {@code PackageManager} succeeding or failing to install
     * the package and reports this to the Event Log.
     */
    void setFlowFinishedWithPackageManagerResult(int packageManagerResult) {
        mPackageManagerInstallResult = packageManagerResult;
        if (packageManagerResult == PackageManager.INSTALL_SUCCEEDED) {
            setFlowFinished(
                    InstallFlowAnalytics.RESULT_SUCCESS);
        } else {
            setFlowFinished(
                    InstallFlowAnalytics.RESULT_PACKAGE_MANAGER_INSTALL_FAILED);
        }
    }

    /**
     * Marks this flow as finished and reports this to the Event Log.
     */
    void setFlowFinished(byte result) {
        if (mLogged) {
            return;
        }
        mResult = result;
        mEndTimestampMillis = SystemClock.elapsedRealtime();
        writeToEventLog();
    }

    private void writeToEventLog() {
        byte packageManagerInstallResultByte = 0;
        if (mResult == RESULT_PACKAGE_MANAGER_INSTALL_FAILED) {
            // PackageManager install error codes are negative, starting from -1 and going to
            // -111 (at the moment). We thus store them in negated form.
            packageManagerInstallResultByte = clipUnsignedValueToUnsignedByte(
                    -mPackageManagerInstallResult);
        }

        final int resultAndFlags = (mResult & 0xff)
                | ((packageManagerInstallResultByte & 0xff) << 8)
                | ((mFlags & 0xffff) << 16);

        // Total elapsed time from start to end, in milliseconds.
        final int totalElapsedTime =
                clipUnsignedLongToUnsignedInt(mEndTimestampMillis - mStartTimestampMillis);

        // Total elapsed time from start till information about the package being installed was
        // obtained, in milliseconds.
        final int elapsedTimeTillPackageInfoObtained = (isPackageInfoObtained())
                ? clipUnsignedLongToUnsignedInt(
                        mPackageInfoObtainedTimestampMillis - mStartTimestampMillis)
                : 0;

        // Total elapsed time from start till Install button clicked, in milliseconds
        // milliseconds.
        final int elapsedTimeTillInstallButtonClick = (isInstallButtonClicked())
                ? clipUnsignedLongToUnsignedInt(
                            mInstallButtonClickTimestampMillis - mStartTimestampMillis)
                : 0;

        // If this user has consented to app verification, augment the logged event with the hash of
        // the contents of the APK.
        if (((mFlags & FLAG_FILE_URI) != 0)
                && ((mFlags & FLAG_VERIFY_APPS_ENABLED) != 0)
                && (isUserConsentToVerifyAppsGranted())) {
            // Log the hash of the APK's contents.
            // Reading the APK may take a while -- perform in background.
            AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
                @Override
                public void run() {
                    byte[] digest = null;
                    try {
                        digest = getPackageContentsDigest();
                    } catch (IOException e) {
                        Log.w(TAG, "Failed to hash APK contents", e);
                    } finally {
                        String digestHex = (digest != null)
                                ? IntegralToString.bytesToHexString(digest, false)
                                : "";
                        EventLogTags.writeInstallPackageAttempt(
                                resultAndFlags,
                                totalElapsedTime,
                                elapsedTimeTillPackageInfoObtained,
                                elapsedTimeTillInstallButtonClick,
                                digestHex);
                    }
                }
            });
        } else {
            // Do not log the hash of the APK's contents
            EventLogTags.writeInstallPackageAttempt(
                    resultAndFlags,
                    totalElapsedTime,
                    elapsedTimeTillPackageInfoObtained,
                    elapsedTimeTillInstallButtonClick,
                    "");
        }
        mLogged = true;

        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "Analytics:"
                    + "\n\tinstallsFromUnknownSourcesPermitted: "
                        + isInstallsFromUnknownSourcesPermitted()
                    + "\n\tinstallRequestFromUnknownSource: " + isInstallRequestFromUnknownSource()
                    + "\n\tverifyAppsEnabled: " + isVerifyAppsEnabled()
                    + "\n\tappVerifierInstalled: " + isAppVerifierInstalled()
                    + "\n\tfileUri: " + isFileUri()
                    + "\n\treplace: " + isReplace()
                    + "\n\tsystemApp: " + isSystemApp()
                    + "\n\tpackageInfoObtained: " + isPackageInfoObtained()
                    + "\n\tinstallButtonClicked: " + isInstallButtonClicked()
                    + "\n\tpermissionsDisplayed: " + isPermissionsDisplayed()
                    + "\n\tnewPermissionsDisplayed: " + isNewPermissionsDisplayed()
                    + "\n\tallPermissionsDisplayed: " + isAllPermissionsDisplayed()
                    + "\n\tnewPermissionsFound: " + isNewPermissionsFound()
                    + "\n\tresult: " + mResult
                    + "\n\tpackageManagerInstallResult: " + mPackageManagerInstallResult
                    + "\n\ttotalDuration: " + (mEndTimestampMillis - mStartTimestampMillis) + " ms"
                    + "\n\ttimeTillPackageInfoObtained: "
                        + ((isPackageInfoObtained())
                            ? ((mPackageInfoObtainedTimestampMillis - mStartTimestampMillis)
                                    + " ms")
                            : "n/a")
                    + "\n\ttimeTillInstallButtonClick: "
                        + ((isInstallButtonClicked())
                            ? ((mInstallButtonClickTimestampMillis - mStartTimestampMillis) + " ms")
                            : "n/a"));
            Log.v(TAG, "Wrote to Event Log: 0x" + Long.toString(resultAndFlags & 0xffffffffL, 16)
                    + ", " + totalElapsedTime
                    + ", " + elapsedTimeTillPackageInfoObtained
                    + ", " + elapsedTimeTillInstallButtonClick);
        }
    }

    private static final byte clipUnsignedValueToUnsignedByte(long value) {
        if (value < 0) {
            return 0;
        } else if (value > 0xff) {
            return (byte) 0xff;
        } else {
            return (byte) value;
        }
    }

    private static final int clipUnsignedLongToUnsignedInt(long value) {
        if (value < 0) {
            return 0;
        } else if (value > 0xffffffffL) {
            return 0xffffffff;
        } else {
            return (int) value;
        }
    }

    /**
     * Sets or clears the specified flag in the {@link #mFlags} field.
     */
    private void setFlagState(int flag, boolean set) {
        if (set) {
            mFlags |= flag;
        } else {
            mFlags &= ~flag;
        }
    }

    /**
     * Checks whether the specified flag is set in the {@link #mFlags} field.
     */
    private boolean isFlagSet(int flag) {
        return (mFlags & flag) == flag;
    }

    /**
     * Checks whether the user has consented to app verification.
     */
    private boolean isUserConsentToVerifyAppsGranted() {
        return Settings.Secure.getInt(
                mContext.getContentResolver(),
                Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT, 0) != 0;
    }

    /**
     * Gets the digest of the contents of the package being installed.
     */
    private byte[] getPackageContentsDigest() throws IOException {
        File file = new File(Uri.parse(mPackageUri).getPath());
        return getSha256ContentsDigest(file);
    }

    /**
     * Gets the SHA-256 digest of the contents of the specified file.
     */
    private static byte[] getSha256ContentsDigest(File file) throws IOException {
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256 not available", e);
        }

        byte[] buf = new byte[8192];
        InputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(file), buf.length);
            int chunkSize;
            while ((chunkSize = in.read(buf)) != -1) {
                digest.update(buf, 0, chunkSize);
            }
        } finally {
            IoUtils.closeQuietly(in);
        }
        return digest.digest();
    }
}