/*
 * Copyright (C) 2015 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.wear;

import android.annotation.Nullable;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;

import com.android.packageinstaller.DeviceUtils;
import com.android.packageinstaller.PackageUtil;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Service that will install/uninstall packages. It will check for permissions and features as well.
 *
 * -----------
 *
 * Debugging information:
 *
 *  Install Action example:
 *  adb shell am startservice -a com.android.packageinstaller.wear.INSTALL_PACKAGE \
 *     -t vnd.android.cursor.item/wearable_apk \
 *     -d content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/wearable/com.google.android.gms/apk \
 *     --es android.intent.extra.INSTALLER_PACKAGE_NAME com.google.android.gms \
 *     --ez com.google.android.clockwork.EXTRA_CHECK_PERMS false \
 *     --eu com.google.android.clockwork.EXTRA_PERM_URI content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/permissions \
 *     com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService
 *
 *  Retry GMS:
 *  adb shell am startservice -a com.android.packageinstaller.wear.RETRY_GMS \
 *     com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService
 */
public class WearPackageInstallerService extends Service {
    private static final String TAG = "WearPkgInstallerService";

    private static final String KEY_PERM_URI =
            "com.google.android.clockwork.EXTRA_PERM_URI";
    private static final String KEY_CHECK_PERMS =
            "com.google.android.clockwork.EXTRA_CHECK_PERMS";
    private static final String KEY_SKIP_IF_SAME_VERSION =
            "com.google.android.clockwork.EXTRA_SKIP_IF_SAME_VERSION";
    private static final String KEY_COMPRESSION_ALG =
            "com.google.android.clockwork.EXTRA_KEY_COMPRESSION_ALG";
    private static final String KEY_COMPANION_SDK_VERSION =
            "com.google.android.clockwork.EXTRA_KEY_COMPANION_SDK_VERSION";
    private static final String KEY_COMPANION_DEVICE_VERSION =
            "com.google.android.clockwork.EXTRA_KEY_COMPANION_DEVICE_VERSION";

    private static final String KEY_PACKAGE_NAME =
            "com.google.android.clockwork.EXTRA_PACKAGE_NAME";
    private static final String KEY_APP_LABEL = "com.google.android.clockwork.EXTRA_APP_LABEL";
    private static final String KEY_APP_ICON_URI =
            "com.google.android.clockwork.EXTRA_APP_ICON_URI";
    private static final String KEY_PERMS_LIST = "com.google.android.clockwork.EXTRA_PERMS_LIST";
    private static final String KEY_HAS_LAUNCHER =
            "com.google.android.clockwork.EXTRA_HAS_LAUNCHER";

    private static final String HOME_APP_PACKAGE_NAME = "com.google.android.wearable.app";
    private static final String SHOW_PERMS_SERVICE_CLASS =
            "com.google.android.clockwork.packagemanager.ShowPermsService";

    private static final String ASSET_URI_ARG = "assetUri";
    private static final String PACKAGE_NAME_ARG = "packageName";
    private static final String PERM_URI_ARG = "permUri";
    private static final String START_ID_ARG = "startId";
    private static final String CHECK_PERMS_ARG = "checkPerms";
    private static final String SKIP_IF_SAME_VERSION_ARG = "skipIfSameVersion";
    private static final String COMPRESSION_ALG = "compressionAlg";
    private static final String COMPANION_SDK_VERSION = "companionSdkVersion";
    private static final String COMPANION_DEVICE_VERSION = "companionDeviceVersion";

    /**
     * Normally sent by the Play store (See http://go/playstore-gms_updated), we instead
     * broadcast, ourselves. http://b/17387718
     */
    private static final String GMS_UPDATED_BROADCAST = "com.google.android.gms.GMS_UPDATED";
    public static final String GMS_PACKAGE_NAME = "com.google.android.gms";

    private final int START_INSTALL = 1;
    private final int START_UNINSTALL = 2;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case START_INSTALL:
                    installPackage(msg.getData().getString(PACKAGE_NAME_ARG),
                            (Uri) msg.getData().getParcelable(ASSET_URI_ARG),
                            (Uri) msg.getData().getParcelable(PERM_URI_ARG),
                            msg.getData().getInt(START_ID_ARG),
                            msg.getData().getBoolean(CHECK_PERMS_ARG),
                            msg.getData().getBoolean(SKIP_IF_SAME_VERSION_ARG),
                            msg.getData().getString(COMPRESSION_ALG),
                            msg.getData().getInt(COMPANION_SDK_VERSION),
                            msg.getData().getInt(COMPANION_DEVICE_VERSION));
                    break;
                case START_UNINSTALL:
                    uninstallPackage(msg.getData().getString(PACKAGE_NAME_ARG),
                            msg.getData().getInt(START_ID_ARG));
                    break;
            }
        }
    }
    private ServiceHandler mServiceHandler;

    private static volatile PowerManager.WakeLock lockStatic = null;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("PackageInstallerThread",
                Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        mServiceHandler = new ServiceHandler(thread.getLooper());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (!DeviceUtils.isWear(this)) {
            Log.w(TAG, "Not running on wearable");
            return START_NOT_STICKY;
        }
        PowerManager.WakeLock lock = getLock(this.getApplicationContext());
        if (!lock.isHeld()) {
            lock.acquire();
        }
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Got install/uninstall request " + intent);
        }
        if (intent != null) {
            if (Intent.ACTION_INSTALL_PACKAGE.equals(intent.getAction())) {
                final Message msg = mServiceHandler.obtainMessage(START_INSTALL);
                final Bundle startInstallArgs = new Bundle();
                startInstallArgs.putParcelable(ASSET_URI_ARG, intent.getData());
                startInstallArgs.putString(PACKAGE_NAME_ARG, intent.getStringExtra(
                        Intent.EXTRA_INSTALLER_PACKAGE_NAME));
                startInstallArgs.putInt(START_ID_ARG, startId);
                Uri permUri = intent.getParcelableExtra(KEY_PERM_URI);
                startInstallArgs.putParcelable(PERM_URI_ARG, permUri);
                startInstallArgs.putBoolean(CHECK_PERMS_ARG,
                        intent.getBooleanExtra(KEY_CHECK_PERMS, true));
                startInstallArgs.putBoolean(SKIP_IF_SAME_VERSION_ARG,
                        intent.getBooleanExtra(KEY_SKIP_IF_SAME_VERSION, false));
                startInstallArgs.putString(COMPRESSION_ALG,
                        intent.getStringExtra(KEY_COMPRESSION_ALG));
                startInstallArgs.putInt(COMPANION_SDK_VERSION,
                        intent.getIntExtra(KEY_COMPANION_SDK_VERSION, 0));
                startInstallArgs.putInt(COMPANION_DEVICE_VERSION,
                        intent.getIntExtra(KEY_COMPANION_DEVICE_VERSION, 0));
                msg.setData(startInstallArgs);
                mServiceHandler.sendMessage(msg);
            } else if (Intent.ACTION_UNINSTALL_PACKAGE.equals(intent.getAction())) {
                Message msg = mServiceHandler.obtainMessage(START_UNINSTALL);
                Bundle startUninstallArgs = new Bundle();
                startUninstallArgs.putString(PACKAGE_NAME_ARG, intent.getStringExtra(
                        Intent.EXTRA_INSTALLER_PACKAGE_NAME));
                startUninstallArgs.putInt(START_ID_ARG, startId);
                msg.setData(startUninstallArgs);
                mServiceHandler.sendMessage(msg);
            }
        }
        return START_NOT_STICKY;
    }

    private void installPackage(String packageName, Uri packageUri, Uri permUri, int startId,
            boolean checkPerms, boolean skipIfSameVersion, @Nullable String compressionAlg,
            int companionSdkVersion, int companionDeviceVersion) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Installing package: " + packageName + ", packageUri: " + packageUri +
                    ",permUri: " + permUri + ", startId: " + startId + ", checkPerms: " +
                    checkPerms + ", skipIfSameVersion: " + skipIfSameVersion +
                    ", compressionAlg: " + compressionAlg + ", companionSdkVersion: " +
                    companionSdkVersion + ", companionDeviceVersion: " + companionDeviceVersion);
        }
        final PackageManager pm = getPackageManager();
        File tempFile = null;
        int installFlags = 0;
        PowerManager.WakeLock lock = getLock(this.getApplicationContext());
        boolean messageSent = false;
        try {
            PackageInfo existingPkgInfo = null;
            try {
                existingPkgInfo = pm.getPackageInfo(packageName,
                        PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS);
                if(existingPkgInfo != null) {
                    installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
                }
            } catch (PackageManager.NameNotFoundException e) {
                // Ignore this exception. We could not find the package, will treat as a new
                // installation.
            }
            if((installFlags & PackageManager.INSTALL_REPLACE_EXISTING )!= 0) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Replacing package:" + packageName);
                }
            }
            ParcelFileDescriptor parcelFd = getContentResolver()
                    .openFileDescriptor(packageUri, "r");
            tempFile = WearPackageUtil.getFileFromFd(WearPackageInstallerService.this,
                    parcelFd, packageName, compressionAlg);
            if (tempFile == null) {
                Log.e(TAG, "Could not create a temp file from FD for " + packageName);
                return;
            }
            PackageParser.Package pkg = PackageUtil.getPackageInfo(tempFile);
            if (pkg == null) {
                Log.e(TAG, "Could not parse apk information for " + packageName);
                return;
            }

            if (!pkg.packageName.equals(packageName)) {
                Log.e(TAG, "Wearable Package Name has to match what is provided for " +
                        packageName);
                return;
            }

            List<String> wearablePerms = pkg.requestedPermissions;

            // Log if the installed pkg has a higher version number.
            if (existingPkgInfo != null) {
                if (existingPkgInfo.versionCode == pkg.mVersionCode) {
                    if (skipIfSameVersion) {
                        Log.w(TAG, "Version number (" + pkg.mVersionCode +
                                ") of new app is equal to existing app for " + packageName +
                                "; not installing due to versionCheck");
                        return;
                    } else {
                        Log.w(TAG, "Version number of new app (" + pkg.mVersionCode +
                                ") is equal to existing app for " + packageName);
                    }
                } else if (existingPkgInfo.versionCode > pkg.mVersionCode) {
                    Log.w(TAG, "Version number of new app (" + pkg.mVersionCode +
                            ") is lower than existing app ( " + existingPkgInfo.versionCode +
                            ") for " + packageName);
                }

                // Following the Android Phone model, we should only check for permissions for any
                // newly defined perms.
                if (existingPkgInfo.requestedPermissions != null) {
                    for (int i = 0; i < existingPkgInfo.requestedPermissions.length; ++i) {
                        // If the permission is granted, then we will not ask to request it again.
                        if ((existingPkgInfo.requestedPermissionsFlags[i] &
                                PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
                            if (Log.isLoggable(TAG, Log.DEBUG)) {
                                Log.d(TAG, existingPkgInfo.requestedPermissions[i] +
                                        " is already granted for " + packageName);
                            }
                            wearablePerms.remove(existingPkgInfo.requestedPermissions[i]);
                        }
                    }
                }
            }

            // Check permissions on both the new wearable package and also on the already installed
            // wearable package.
            // If the app is targeting API level 23, we will also start a service in ClockworkHome
            // which will ultimately prompt the user to accept/reject permissions.
            if (checkPerms && !checkPermissions(pkg, companionSdkVersion, companionDeviceVersion,
                    permUri, wearablePerms, tempFile)) {
                Log.w(TAG, "Wearable does not have enough permissions.");
                return;
            }

            // Check that the wearable has all the features.
            boolean hasAllFeatures = true;
            if (pkg.reqFeatures != null) {
                for (FeatureInfo feature : pkg.reqFeatures) {
                    if (feature.name != null && !pm.hasSystemFeature(feature.name) &&
                            (feature.flags & FeatureInfo.FLAG_REQUIRED) != 0) {
                        Log.e(TAG, "Wearable does not have required feature: " + feature +
                                " for " + packageName);
                        hasAllFeatures = false;
                    }
                }
            }

            if (!hasAllFeatures) {
                return;
            }

            // Finally install the package.
            pm.installPackage(Uri.fromFile(tempFile),
                    new PackageInstallObserver(this, lock, startId, packageName),
                        installFlags, packageName);
            messageSent = true;
            Log.i(TAG, "Sent installation request for " + packageName);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Could not find the file with URI " + packageUri, e);
        } finally {
            if (!messageSent) {
                // Some error happened. If the message has been sent, we can wait for the observer
                // which will finish the service.
                if (tempFile != null) {
                    tempFile.delete();
                }
                finishService(lock, startId);
            }
        }
    }

    private void uninstallPackage(String packageName, int startId) {
        final PackageManager pm = getPackageManager();
        PowerManager.WakeLock lock = getLock(this.getApplicationContext());
        pm.deletePackage(packageName, new PackageDeleteObserver(lock, startId),
                PackageManager.DELETE_ALL_USERS);
        startPermsServiceForUninstall(packageName);
        Log.i(TAG, "Sent delete request for " + packageName);
    }

    private boolean checkPermissions(PackageParser.Package pkg, int companionSdkVersion,
            int companionDeviceVersion, Uri permUri, List<String> wearablePermissions,
            File apkFile) {
        // If the Wear App is targeted for M-release, since the permission model has been changed,
        // permissions may not be granted on the phone yet. We need a different flow for user to
        // accept these permissions.
        //
        // Assumption: Code is running on E-release, so Wear is always running M.
        // - Case 1: If the Wear App(WA) is targeting 23, always choose the M model (4 cases)
        // - Case 2: Else if the Phone App(PA) is targeting 23 and Phone App(P) is running on M,
        // show a Dialog so that the user can accept all perms (1 case)
        //   - Also show a warning to the developer if the watch is targeting M
        // - Case 3: If Case 2 is false, then the behavior on the phone is pre-M. Stick to pre-M
        // behavior on watch (as long as we don't hit case 1).
        //   - 3a: WA(22) PA(22) P(22) -> watch app is not targeting 23
        //   - 3b: WA(22) PA(22) P(23) -> watch app is not targeting 23
        //   - 3c: WA(22) PA(23) P(22) -> watch app is not targeting 23
        // - Case 4: We did not get Companion App's/Device's version, always show dialog to user to
        // accept permissions. (This happens if the AndroidWear Companion App is really old).
        boolean isWearTargetingM =
                pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
        if (isWearTargetingM) { // Case 1
            // Install the app if Wear App is ready for the new perms model.
            return true;
        }

        List<String> unavailableWearablePerms = getWearPermsNotGrantedOnPhone(pkg.packageName,
                permUri, wearablePermissions);
        if (unavailableWearablePerms == null) {
            return false;
        }

        if (unavailableWearablePerms.size() == 0) {
            // All permissions requested by the watch are already granted on the phone, no need
            // to do anything.
            return true;
        }

        // Cases 2 and 4.
        boolean isCompanionTargetingM = companionSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
        boolean isCompanionRunningM = companionDeviceVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
        if (isCompanionTargetingM) { // Case 2 Warning
            Log.w(TAG, "MNC: Wear app's targetSdkVersion should be at least 23, if " +
                    "phone app is targeting at least 23, will continue.");
        }
        if ((isCompanionTargetingM && isCompanionRunningM) || // Case 2
                companionSdkVersion == 0 || companionDeviceVersion == 0) { // Case 4
            startPermsServiceForInstall(pkg, apkFile, unavailableWearablePerms);
        }

        // Case 3a-3c.
        return false;
    }

    /**
     * Given a {@string packageName} corresponding to a phone app, query the provider for all the
     * perms that are granted.
     * @return null if there is an error retrieving this info
     *         else, a list of all the wearable perms that are not in the list of granted perms of
     * the phone.
     */
    private List<String> getWearPermsNotGrantedOnPhone(String packageName, Uri permUri,
            List<String> wearablePermissions) {
        if (permUri == null) {
            Log.e(TAG, "Permission URI is null");
            return null;
        }
        Cursor permCursor = getContentResolver().query(permUri, null, null, null, null);
        if (permCursor == null) {
            Log.e(TAG, "Could not get the cursor for the permissions");
            return null;
        }

        Set<String> grantedPerms = new HashSet<>();
        Set<String> ungrantedPerms = new HashSet<>();
        while(permCursor.moveToNext()) {
            // Make sure that the MatrixCursor returned by the ContentProvider has 2 columns and
            // verify their types.
            if (permCursor.getColumnCount() == 2
                    && Cursor.FIELD_TYPE_STRING == permCursor.getType(0)
                    && Cursor.FIELD_TYPE_INTEGER == permCursor.getType(1)) {
                String perm = permCursor.getString(0);
                Integer granted = permCursor.getInt(1);
                if (granted == 1) {
                    grantedPerms.add(perm);
                } else {
                    ungrantedPerms.add(perm);
                }
            }
        }
        permCursor.close();

        ArrayList<String> unavailableWearablePerms = new ArrayList<>();
        for (String wearablePerm : wearablePermissions) {
            if (!grantedPerms.contains(wearablePerm)) {
                unavailableWearablePerms.add(wearablePerm);
                if (!ungrantedPerms.contains(wearablePerm)) {
                    // This is an error condition. This means that the wearable has permissions that
                    // are not even declared in its host app. This is a developer error.
                    Log.e(TAG, "Wearable " + packageName + " has a permission \"" + wearablePerm
                            + "\" that is not defined in the host application's manifest.");
                } else {
                    Log.w(TAG, "Wearable " + packageName + " has a permission \"" + wearablePerm +
                            "\" that is not granted in the host application.");
                }
            }
        }
        return unavailableWearablePerms;
    }

    private void finishService(PowerManager.WakeLock lock, int startId) {
        if (lock.isHeld()) {
            lock.release();
        }
        stopSelf(startId);
    }

    private synchronized PowerManager.WakeLock getLock(Context context) {
        if (lockStatic == null) {
            PowerManager mgr =
                    (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            lockStatic = mgr.newWakeLock(
                    PowerManager.PARTIAL_WAKE_LOCK, context.getClass().getSimpleName());
            lockStatic.setReferenceCounted(true);
        }
        return lockStatic;
    }

    private void startPermsServiceForInstall(final PackageParser.Package pkg, final File apkFile,
            List<String> unavailableWearablePerms) {
        final String packageName = pkg.packageName;

        Intent showPermsIntent = new Intent()
                .setComponent(new ComponentName(HOME_APP_PACKAGE_NAME, SHOW_PERMS_SERVICE_CLASS))
                .setAction(Intent.ACTION_INSTALL_PACKAGE);
        final PackageManager pm = getPackageManager();
        pkg.applicationInfo.publicSourceDir = apkFile.getPath();
        final CharSequence label = pkg.applicationInfo.loadLabel(pm);
        final Uri iconUri = getIconFileUri(packageName, pkg.applicationInfo.loadIcon(pm));
        if (TextUtils.isEmpty(label) || iconUri == null) {
            Log.e(TAG, "MNC: Could not launch service since either label " + label +
                    ", or icon Uri " + iconUri + " is invalid.");
        } else {
            showPermsIntent.putExtra(KEY_APP_LABEL, label);
            showPermsIntent.putExtra(KEY_APP_ICON_URI, iconUri);
            showPermsIntent.putExtra(KEY_PACKAGE_NAME, packageName);
            showPermsIntent.putExtra(KEY_PERMS_LIST,
                    unavailableWearablePerms.toArray(new String[0]));
            showPermsIntent.putExtra(KEY_HAS_LAUNCHER, WearPackageUtil.hasLauncherActivity(pkg));

            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "MNC: Launching Intent " + showPermsIntent + " for " + packageName +
                        " with name " + label);
            }
            startService(showPermsIntent);
        }
    }

    private void startPermsServiceForUninstall(final String packageName) {
        Intent showPermsIntent = new Intent()
                .setComponent(new ComponentName(HOME_APP_PACKAGE_NAME, SHOW_PERMS_SERVICE_CLASS))
                .setAction(Intent.ACTION_UNINSTALL_PACKAGE);
        showPermsIntent.putExtra(KEY_PACKAGE_NAME, packageName);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Launching Intent " + showPermsIntent + " for " + packageName);
        }
        startService(showPermsIntent);
    }

    private Uri getIconFileUri(final String packageName, final Drawable d) {
        if (d == null || !(d instanceof BitmapDrawable)) {
            Log.e(TAG, "Drawable is not a BitmapDrawable for " + packageName);
            return null;
        }
        File iconFile = WearPackageUtil.getIconFile(this, packageName);

        if (iconFile == null) {
            Log.e(TAG, "Could not get icon file for " + packageName);
            return null;
        }

        FileOutputStream fos = null;
        try {
            // Convert bitmap to byte array
            Bitmap bitmap = ((BitmapDrawable) d).getBitmap();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);

            // Write the bytes into the file
            fos = new FileOutputStream(iconFile);
            fos.write(bos.toByteArray());
            fos.flush();

            return WearPackageIconProvider.getUriForPackage(packageName);
        } catch (IOException e) {
            Log.e(TAG, "Could not convert drawable to icon file for package " + packageName, e);
            return null;
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }

    private class PackageInstallObserver extends IPackageInstallObserver.Stub {
        private Context mContext;
        private PowerManager.WakeLock mWakeLock;
        private int mStartId;
        private String mApplicationPackageName;
        private PackageInstallObserver(Context context, PowerManager.WakeLock wakeLock,
                int startId, String applicationPackageName) {
            mContext = context;
            mWakeLock = wakeLock;
            mStartId = startId;
            mApplicationPackageName = applicationPackageName;
        }

        public void packageInstalled(String packageName, int returnCode) {
            try {
                // If installation failed, bail out and remove the ShowPermsStore entry
                if (returnCode < 0) {
                    Log.e(TAG, "Package install failed " + mApplicationPackageName
                            + ", returnCode " + returnCode);
                    WearPackageUtil.removeFromPermStore(mContext, mApplicationPackageName);
                    return;
                }

                Log.i(TAG, "Package " + packageName + " was installed.");

                // Delete tempFile from the file system.
                File tempFile = WearPackageUtil.getTemporaryFile(mContext, packageName);
                if (tempFile != null) {
                    tempFile.delete();
                }

                // Broadcast the "UPDATED" gmscore intent, normally sent by play store.
                // TODO: Remove this broadcast if/when we get the play store to do this for us.
                if (GMS_PACKAGE_NAME.equals(packageName)) {
                    Intent gmsInstalledIntent = new Intent(GMS_UPDATED_BROADCAST);
                    gmsInstalledIntent.setPackage(GMS_PACKAGE_NAME);
                    mContext.sendBroadcast(gmsInstalledIntent);
                }
            } finally {
                finishService(mWakeLock, mStartId);
            }
        }
    }

    private class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
        private PowerManager.WakeLock mWakeLock;
        private int mStartId;

        private PackageDeleteObserver(PowerManager.WakeLock wakeLock, int startId) {
            mWakeLock = wakeLock;
            mStartId = startId;
        }

        public void packageDeleted(String packageName, int returnCode) {
            try {
                if (returnCode >= 0) {
                    Log.i(TAG, "Package " + packageName + " was uninstalled.");
                } else {
                    Log.e(TAG, "Package uninstall failed " + packageName + ", returnCode " +
                            returnCode);
                }
            } finally {
                finishService(mWakeLock, mStartId);
            }
        }
    }
}
