/*
 * Copyright (C) 2017 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.settings.applications.appinfo;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
import android.util.Log;
import android.webkit.IWebViewUpdateService;

import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.AppEntry;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class AppActionButtonPreferenceController extends BasePreferenceController
        implements AppInfoDashboardFragment.Callback {

    private static final String TAG = "AppActionButtonControl";
    private static final String KEY_ACTION_BUTTONS = "action_buttons";

    @VisibleForTesting
    ActionButtonPreference mActionButtons;
    private final AppInfoDashboardFragment mParent;
    private final String mPackageName;
    private final HashSet<String> mHomePackages = new HashSet<>();
    private final ApplicationFeatureProvider mApplicationFeatureProvider;

    private int mUserId;
    private DevicePolicyManager mDpm;
    private UserManager mUserManager;
    private PackageManager mPm;

    private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final boolean enabled = getResultCode() != Activity.RESULT_CANCELED;
            Log.d(TAG, "Got broadcast response: Restart status for "
                    + mParent.getAppEntry().info.packageName + " " + enabled);
            updateForceStopButton(enabled);
        }
    };

    public AppActionButtonPreferenceController(Context context, AppInfoDashboardFragment parent,
            String packageName) {
        super(context, KEY_ACTION_BUTTONS);
        mParent = parent;
        mPackageName = packageName;
        mUserId = UserHandle.myUserId();
        mApplicationFeatureProvider = FeatureFactory.getFactory(context)
                .getApplicationFeatureProvider(context);
    }

    @Override
    public int getAvailabilityStatus() {
        return AppUtils.isInstant(mParent.getPackageInfo().applicationInfo)
                ? DISABLED_FOR_USER : AVAILABLE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mActionButtons = ((ActionButtonPreference) screen.findPreference(KEY_ACTION_BUTTONS))
                .setButton2Text(R.string.force_stop)
                .setButton2Positive(false)
                .setButton2Enabled(false);
    }

    @Override
    public void refreshUi() {
        if (mPm == null) {
            mPm = mContext.getPackageManager();
        }
        if (mDpm == null) {
            mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
        }
        if (mUserManager == null) {
            mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        }
        final AppEntry appEntry = mParent.getAppEntry();
        final PackageInfo packageInfo = mParent.getPackageInfo();

        // Get list of "home" apps and trace through any meta-data references
        final List<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
        mPm.getHomeActivities(homeActivities);
        mHomePackages.clear();
        for (int i = 0; i < homeActivities.size(); i++) {
            final ResolveInfo ri = homeActivities.get(i);
            final String activityPkg = ri.activityInfo.packageName;
            mHomePackages.add(activityPkg);

            // Also make sure to include anything proxying for the home app
            final Bundle metadata = ri.activityInfo.metaData;
            if (metadata != null) {
                final String metaPkg = metadata.getString(ActivityManager.META_HOME_ALTERNATE);
                if (signaturesMatch(metaPkg, activityPkg)) {
                    mHomePackages.add(metaPkg);
                }
            }
        }

        checkForceStop(appEntry, packageInfo);
        initUninstallButtons(appEntry, packageInfo);
    }

    @VisibleForTesting
    void initUninstallButtons(AppEntry appEntry, PackageInfo packageInfo) {
        final boolean isBundled = (appEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
        boolean enabled;
        if (isBundled) {
            enabled = handleDisableable(appEntry, packageInfo);
        } else {
            enabled = initUninstallButtonForUserApp();
        }
        // If this is a device admin, it can't be uninstalled or disabled.
        // We do this here so the text of the button is still set correctly.
        if (isBundled && mDpm.packageHasActiveAdmins(packageInfo.packageName)) {
            enabled = false;
        }

        // We don't allow uninstalling DO/PO on *any* users, because if it's a system app,
        // "uninstall" is actually "downgrade to the system version + disable", and "downgrade"
        // will clear data on all users.
        if (Utils.isProfileOrDeviceOwner(mUserManager, mDpm, packageInfo.packageName)) {
            enabled = false;
        }

        // Don't allow uninstalling the device provisioning package.
        if (Utils.isDeviceProvisioningPackage(mContext.getResources(), appEntry.info.packageName)) {
            enabled = false;
        }

        // If the uninstall intent is already queued, disable the uninstall button
        if (mDpm.isUninstallInQueue(mPackageName)) {
            enabled = false;
        }

        // Home apps need special handling.  Bundled ones we don't risk downgrading
        // because that can interfere with home-key resolution.  Furthermore, we
        // can't allow uninstallation of the only home app, and we don't want to
        // allow uninstallation of an explicitly preferred one -- the user can go
        // to Home settings and pick a different one, after which we'll permit
        // uninstallation of the now-not-default one.
        if (enabled && mHomePackages.contains(packageInfo.packageName)) {
            if (isBundled) {
                enabled = false;
            } else {
                ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
                ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities);
                if (currentDefaultHome == null) {
                    // No preferred default, so permit uninstall only when
                    // there is more than one candidate
                    enabled = (mHomePackages.size() > 1);
                } else {
                    // There is an explicit default home app -- forbid uninstall of
                    // that one, but permit it for installed-but-inactive ones.
                    enabled = !packageInfo.packageName.equals(currentDefaultHome.getPackageName());
                }
            }
        }

        if (RestrictedLockUtils.hasBaseUserRestriction(
                mContext, UserManager.DISALLOW_APPS_CONTROL, mUserId)) {
            enabled = false;
        }

        try {
            final IWebViewUpdateService webviewUpdateService =
                    IWebViewUpdateService.Stub.asInterface(
                            ServiceManager.getService("webviewupdate"));
            if (webviewUpdateService.isFallbackPackage(appEntry.info.packageName)) {
                enabled = false;
            }
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }

        mActionButtons.setButton1Enabled(enabled);
        if (enabled) {
            // Register listener
            mActionButtons.setButton1OnClickListener(v -> mParent.handleUninstallButtonClick());
        }
    }

    @VisibleForTesting
    boolean initUninstallButtonForUserApp() {
        boolean enabled = true;
        final PackageInfo packageInfo = mParent.getPackageInfo();
        if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0
                && mUserManager.getUsers().size() >= 2) {
            // When we have multiple users, there is a separate menu
            // to uninstall for all users.
            enabled = false;
        } else if (AppUtils.isInstant(packageInfo.applicationInfo)) {
            enabled = false;
            mActionButtons.setButton1Visible(false);
        }
        mActionButtons.setButton1Text(R.string.uninstall_text).setButton1Positive(false);
        return enabled;
    }

    @VisibleForTesting
    boolean handleDisableable(AppEntry appEntry, PackageInfo packageInfo) {
        boolean disableable = false;
        // Try to prevent the user from bricking their phone
        // by not allowing disabling of apps signed with the
        // system cert and any launcher app in the system.
        if (mHomePackages.contains(appEntry.info.packageName)
                || Utils.isSystemPackage(mContext.getResources(), mPm, packageInfo)) {
            // Disable button for core system applications.
            mActionButtons
                    .setButton1Text(R.string.disable_text)
                    .setButton1Positive(false);
        } else if (appEntry.info.enabled && appEntry.info.enabledSetting
                != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
            mActionButtons
                    .setButton1Text(R.string.disable_text)
                    .setButton1Positive(false);
            disableable = !mApplicationFeatureProvider.getKeepEnabledPackages()
                    .contains(appEntry.info.packageName);
        } else {
            mActionButtons
                    .setButton1Text(R.string.enable_text)
                    .setButton1Positive(true);
            disableable = true;
        }

        return disableable;
    }

    private void updateForceStopButton(boolean enabled) {
        final boolean disallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
                mContext, UserManager.DISALLOW_APPS_CONTROL, mUserId);
        mActionButtons
                .setButton2Enabled(disallowedBySystem ? false : enabled)
                .setButton2OnClickListener(
                        disallowedBySystem ? null : v -> mParent.handleForceStopButtonClick());
    }

    void checkForceStop(AppEntry appEntry, PackageInfo packageInfo) {
        if (mDpm.packageHasActiveAdmins(packageInfo.packageName)) {
            // User can't force stop device admin.
            Log.w(TAG, "User can't force stop device admin");
            updateForceStopButton(false);
        } else if (mPm.isPackageStateProtected(packageInfo.packageName,
                UserHandle.getUserId(appEntry.info.uid))) {
            Log.w(TAG, "User can't force stop protected packages");
            updateForceStopButton(false);
        } else if (AppUtils.isInstant(packageInfo.applicationInfo)) {
            updateForceStopButton(false);
            mActionButtons.setButton2Visible(false);
        } else if ((appEntry.info.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
            // If the app isn't explicitly stopped, then always show the
            // force stop button.
            Log.w(TAG, "App is not explicitly stopped");
            updateForceStopButton(true);
        } else {
            final Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
                    Uri.fromParts("package", appEntry.info.packageName, null));
            intent.putExtra(Intent.EXTRA_PACKAGES, new String[] {appEntry.info.packageName});
            intent.putExtra(Intent.EXTRA_UID, appEntry.info.uid);
            intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(appEntry.info.uid));
            Log.d(TAG, "Sending broadcast to query restart status for "
                    + appEntry.info.packageName);
            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
                    mCheckKillProcessesReceiver, null, Activity.RESULT_CANCELED, null, null);
        }
    }

    private boolean signaturesMatch(String pkg1, String pkg2) {
        if (pkg1 != null && pkg2 != null) {
            try {
                return mPm.checkSignatures(pkg1, pkg2) >= PackageManager.SIGNATURE_MATCH;
            } catch (Exception e) {
                // e.g. named alternate package not found during lookup;
                // this is an expected case sometimes
            }
        }
        return false;
    }

}
