/*
 * Copyright (C) 2016 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.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.IDevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.graphics.drawable.Icon;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import android.util.Log;
import android.widget.Toast;

import java.util.List;

/**
 * Finish an uninstallation and show Toast on success or failure notification.
 */
public class UninstallFinish extends BroadcastReceiver {
    private static final String LOG_TAG = UninstallFinish.class.getSimpleName();

    private static final String UNINSTALL_FAILURE_CHANNEL = "uninstall failure";

    static final String EXTRA_UNINSTALL_ID = "com.android.packageinstaller.extra.UNINSTALL_ID";
    static final String EXTRA_APP_LABEL = "com.android.packageinstaller.extra.APP_LABEL";

    @Override
    public void onReceive(Context context, Intent intent) {
        int returnCode = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, 0);

        Log.i(LOG_TAG, "Uninstall finished extras=" + intent.getExtras());

        if (returnCode == PackageInstaller.STATUS_PENDING_USER_ACTION) {
            context.startActivity(intent.getParcelableExtra(Intent.EXTRA_INTENT));
            return;
        }

        int uninstallId = intent.getIntExtra(EXTRA_UNINSTALL_ID, 0);
        ApplicationInfo appInfo = intent.getParcelableExtra(
                PackageUtil.INTENT_ATTR_APPLICATION_INFO);
        String appLabel = intent.getStringExtra(EXTRA_APP_LABEL);
        boolean allUsers = intent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false);

        NotificationManager notificationManager =
                context.getSystemService(NotificationManager.class);
        UserManager userManager = context.getSystemService(UserManager.class);

        NotificationChannel uninstallFailureChannel = new NotificationChannel(
                UNINSTALL_FAILURE_CHANNEL,
                context.getString(R.string.uninstall_failure_notification_channel),
                NotificationManager.IMPORTANCE_DEFAULT);
        notificationManager.createNotificationChannel(uninstallFailureChannel);

        Notification.Builder uninstallFailedNotification = new Notification.Builder(context,
                UNINSTALL_FAILURE_CHANNEL);

        switch (returnCode) {
            case PackageInstaller.STATUS_SUCCESS:
                notificationManager.cancel(uninstallId);

                Toast.makeText(context, context.getString(R.string.uninstall_done_app, appLabel),
                        Toast.LENGTH_LONG).show();
                return;
            case PackageInstaller.STATUS_FAILURE_BLOCKED: {
                int legacyStatus = intent.getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS, 0);

                switch (legacyStatus) {
                    case PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER: {
                        IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
                                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
                        // Find out if the package is an active admin for some non-current user.
                        int myUserId = UserHandle.myUserId();
                        UserInfo otherBlockingUser = null;
                        for (UserInfo user : userManager.getUsers()) {
                            // We only catch the case when the user in question is neither the
                            // current user nor its profile.
                            if (isProfileOfOrSame(userManager, myUserId, user.id)) {
                                continue;
                            }

                            try {
                                if (dpm.packageHasActiveAdmins(appInfo.packageName, user.id)) {
                                    otherBlockingUser = user;
                                    break;
                                }
                            } catch (RemoteException e) {
                                Log.e(LOG_TAG, "Failed to talk to package manager", e);
                            }
                        }
                        if (otherBlockingUser == null) {
                            Log.d(LOG_TAG, "Uninstall failed because " + appInfo.packageName
                                    + " is a device admin");

                            addDeviceManagerButton(context, uninstallFailedNotification);
                            setBigText(uninstallFailedNotification, context.getString(
                                    R.string.uninstall_failed_device_policy_manager));
                        } else {
                            Log.d(LOG_TAG, "Uninstall failed because " + appInfo.packageName
                                    + " is a device admin of user " + otherBlockingUser);

                            setBigText(uninstallFailedNotification, String.format(context.getString(
                                    R.string.uninstall_failed_device_policy_manager_of_user),
                                    otherBlockingUser.name));
                        }
                        break;
                    }
                    case PackageManager.DELETE_FAILED_OWNER_BLOCKED: {
                        IPackageManager packageManager = IPackageManager.Stub.asInterface(
                                ServiceManager.getService("package"));

                        List<UserInfo> users = userManager.getUsers();
                        int blockingUserId = UserHandle.USER_NULL;
                        for (int i = 0; i < users.size(); ++i) {
                            final UserInfo user = users.get(i);
                            try {
                                if (packageManager.getBlockUninstallForUser(appInfo.packageName,
                                        user.id)) {
                                    blockingUserId = user.id;
                                    break;
                                }
                            } catch (RemoteException e) {
                                // Shouldn't happen.
                                Log.e(LOG_TAG, "Failed to talk to package manager", e);
                            }
                        }

                        int myUserId = UserHandle.myUserId();
                        if (isProfileOfOrSame(userManager, myUserId, blockingUserId)) {
                            addDeviceManagerButton(context, uninstallFailedNotification);
                        } else {
                            addManageUsersButton(context, uninstallFailedNotification);
                        }

                        if (blockingUserId == UserHandle.USER_NULL) {
                            Log.d(LOG_TAG,
                                    "Uninstall failed for " + appInfo.packageName + " with code "
                                            + returnCode + " no blocking user");
                        } else if (blockingUserId == UserHandle.USER_SYSTEM) {
                            setBigText(uninstallFailedNotification,
                                    context.getString(R.string.uninstall_blocked_device_owner));
                        } else {
                            if (allUsers) {
                                setBigText(uninstallFailedNotification,
                                        context.getString(
                                                R.string.uninstall_all_blocked_profile_owner));
                            } else {
                                setBigText(uninstallFailedNotification, context.getString(
                                        R.string.uninstall_blocked_profile_owner));
                            }
                        }
                        break;
                    }
                    default:
                        Log.d(LOG_TAG, "Uninstall blocked for " + appInfo.packageName
                                + " with legacy code " + legacyStatus);
                } break;
            }
            default:
                Log.d(LOG_TAG, "Uninstall failed for " + appInfo.packageName + " with code "
                        + returnCode);
                break;
        }

        uninstallFailedNotification.setContentTitle(
                context.getString(R.string.uninstall_failed_app, appLabel));
        uninstallFailedNotification.setOngoing(false);
        uninstallFailedNotification.setSmallIcon(R.drawable.ic_error);
        notificationManager.notify(uninstallId, uninstallFailedNotification.build());
    }

    /**
     * Is a profile part of a user?
     *
     * @param userManager The user manager
     * @param userId The id of the user
     * @param profileId The id of the profile
     *
     * @return If the profile is part of the user or the profile parent of the user
     */
    private boolean isProfileOfOrSame(@NonNull UserManager userManager, int userId, int profileId) {
        if (userId == profileId) {
            return true;
        }

        UserInfo parentUser = userManager.getProfileParent(profileId);
        return parentUser != null && parentUser.id == userId;
    }

    /**
     * Set big text for the notification.
     *
     * @param builder The builder of the notification
     * @param text The text to set.
     */
    private void setBigText(@NonNull Notification.Builder builder,
            @NonNull CharSequence text) {
        builder.setStyle(new Notification.BigTextStyle().bigText(text));
    }

    /**
     * Add a button to the notification that links to the user management.
     *
     * @param context The context the notification is created in
     * @param builder The builder of the notification
     */
    private void addManageUsersButton(@NonNull Context context,
            @NonNull Notification.Builder builder) {
        Intent intent = new Intent(Settings.ACTION_USER_SETTINGS);
        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK);

        builder.addAction((new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.ic_settings_multiuser),
                context.getString(R.string.manage_users),
                PendingIntent.getActivity(context, 0, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT))).build());
    }

    /**
     * Add a button to the notification that links to the device policy management.
     *
     * @param context The context the notification is created in
     * @param builder The builder of the notification
     */
    private void addDeviceManagerButton(@NonNull Context context,
            @NonNull Notification.Builder builder) {
        Intent intent = new Intent();
        intent.setClassName("com.android.settings",
                "com.android.settings.Settings$DeviceAdminSettingsActivity");
        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK);

        builder.addAction((new Notification.Action.Builder(
                Icon.createWithResource(context, R.drawable.ic_lock),
                context.getString(R.string.manage_device_administrators),
                PendingIntent.getActivity(context, 0, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT))).build());
    }
}
