/*
 * 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.server.pm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.IPinItemRequest;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.PinItemRequest;
import android.content.pm.ShortcutInfo;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

/**
 * Handles {@link android.content.pm.ShortcutManager#requestPinShortcut} related tasks.
 */
class ShortcutRequestPinProcessor {
    private static final String TAG = ShortcutService.TAG;
    private static final boolean DEBUG = ShortcutService.DEBUG;

    private final ShortcutService mService;
    private final Object mLock;

    /**
     * Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
     */
    private abstract static class PinItemRequestInner extends IPinItemRequest.Stub {
        protected final ShortcutRequestPinProcessor mProcessor;
        private final IntentSender mResultIntent;
        private final int mLauncherUid;

        @GuardedBy("this")
        private boolean mAccepted;

        private PinItemRequestInner(ShortcutRequestPinProcessor processor,
                IntentSender resultIntent, int launcherUid) {
            mProcessor = processor;
            mResultIntent = resultIntent;
            mLauncherUid = launcherUid;
        }

        @Override
        public ShortcutInfo getShortcutInfo() {
            return null;
        }

        @Override
        public AppWidgetProviderInfo getAppWidgetProviderInfo() {
            return null;
        }

        @Override
        public Bundle getExtras() {
            return null;
        }

        /**
         * Returns true if the caller is same as the default launcher app when this request
         * object was created.
         */
        private boolean isCallerValid() {
            return mProcessor.isCallerUid(mLauncherUid);
        }

        @Override
        public boolean isValid() {
            if (!isCallerValid()) {
                return false;
            }
            // TODO When an app calls requestPinShortcut(), all pending requests should be
            // invalidated.
            synchronized (this) {
                return !mAccepted;
            }
        }

        /**
         * Called when the launcher calls {@link PinItemRequest#accept}.
         */
        @Override
        public boolean accept(Bundle options) {
            // Make sure the options are unparcellable by the FW. (e.g. not containing unknown
            // classes.)
            if (!isCallerValid()) {
                throw new SecurityException("Calling uid mismatch");
            }
            Intent extras = null;
            if (options != null) {
                try {
                    options.size();
                    extras = new Intent().putExtras(options);
                } catch (RuntimeException e) {
                    throw new IllegalArgumentException("options cannot be unparceled", e);
                }
            }
            synchronized (this) {
                if (mAccepted) {
                    throw new IllegalStateException("accept() called already");
                }
                mAccepted = true;
            }

            // Pin it and send the result intent.
            if (tryAccept()) {
                mProcessor.sendResultIntent(mResultIntent, extras);
                return true;
            } else {
                return false;
            }
        }

        protected boolean tryAccept() {
            return true;
        }
    }

    /**
     * Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
     */
    private static class PinAppWidgetRequestInner extends PinItemRequestInner {
        final AppWidgetProviderInfo mAppWidgetProviderInfo;
        final Bundle mExtras;

        private PinAppWidgetRequestInner(ShortcutRequestPinProcessor processor,
                IntentSender resultIntent, int launcherUid,
                AppWidgetProviderInfo appWidgetProviderInfo, Bundle extras) {
            super(processor, resultIntent, launcherUid);

            mAppWidgetProviderInfo = appWidgetProviderInfo;
            mExtras = extras;
        }

        @Override
        public AppWidgetProviderInfo getAppWidgetProviderInfo() {
            return mAppWidgetProviderInfo;
        }

        @Override
        public Bundle getExtras() {
            return mExtras;
        }
    }

    /**
     * Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
     */
    private static class PinShortcutRequestInner extends PinItemRequestInner {
        /** Original shortcut passed by the app. */
        public final ShortcutInfo shortcutOriginal;

        /**
         * Cloned shortcut that's passed to the launcher.  The notable difference from
         * {@link #shortcutOriginal} is it must not have the intent.
         */
        public final ShortcutInfo shortcutForLauncher;

        public final String launcherPackage;
        public final int launcherUserId;
        public final boolean preExisting;

        private PinShortcutRequestInner(ShortcutRequestPinProcessor processor,
                ShortcutInfo shortcutOriginal, ShortcutInfo shortcutForLauncher,
                IntentSender resultIntent,
                String launcherPackage, int launcherUserId, int launcherUid, boolean preExisting) {
            super(processor, resultIntent, launcherUid);
            this.shortcutOriginal = shortcutOriginal;
            this.shortcutForLauncher = shortcutForLauncher;
            this.launcherPackage = launcherPackage;
            this.launcherUserId = launcherUserId;
            this.preExisting = preExisting;
        }

        @Override
        public ShortcutInfo getShortcutInfo() {
            return shortcutForLauncher;
        }

        @Override
        protected boolean tryAccept() {
            if (DEBUG) {
                Slog.d(TAG, "Launcher accepted shortcut. ID=" + shortcutOriginal.getId()
                    + " package=" + shortcutOriginal.getPackage());
            }
            return mProcessor.directPinShortcut(this);
        }
    }

    public ShortcutRequestPinProcessor(ShortcutService service, Object lock) {
        mService = service;
        mLock = lock;
    }

    public boolean isRequestPinItemSupported(int callingUserId, int requestType) {
        return getRequestPinConfirmationActivity(callingUserId, requestType) != null;
    }

    /**
     * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)} and
     * {@link android.appwidget.AppWidgetManager#requestPinAppWidget}.
     * In this flow the PinItemRequest is delivered directly to the default launcher app.
     * One of {@param inShortcut} and {@param inAppWidget} is always non-null and the other is
     * always null.
     */
    public boolean requestPinItemLocked(ShortcutInfo inShortcut, AppWidgetProviderInfo inAppWidget,
        Bundle extras, int userId, IntentSender resultIntent) {

        // First, make sure the launcher supports it.

        // Find the confirmation activity in the default launcher.
        final int requestType = inShortcut != null ?
                PinItemRequest.REQUEST_TYPE_SHORTCUT : PinItemRequest.REQUEST_TYPE_APPWIDGET;
        final Pair<ComponentName, Integer> confirmActivity =
                getRequestPinConfirmationActivity(userId, requestType);

        // If the launcher doesn't support it, just return a rejected result and finish.
        if (confirmActivity == null) {
            Log.w(TAG, "Launcher doesn't support requestPinnedShortcut(). Shortcut not created.");
            return false;
        }

        final int launcherUserId = confirmActivity.second;

        // Make sure the launcher user is unlocked. (it's always the parent profile, so should
        // really be unlocked here though.)
        mService.throwIfUserLockedL(launcherUserId);

        // Next, validate the incoming shortcut, etc.
        final PinItemRequest request;
        if (inShortcut != null) {
            request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity);
        } else {
            int launcherUid = mService.injectGetPackageUid(
                    confirmActivity.first.getPackageName(), launcherUserId);
            request = new PinItemRequest(
                    new PinAppWidgetRequestInner(this, resultIntent, launcherUid, inAppWidget,
                            extras),
                    PinItemRequest.REQUEST_TYPE_APPWIDGET);
        }
        return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request,
                requestType);
    }

    /**
     * Handle {@link android.content.pm.ShortcutManager#createShortcutResultIntent(ShortcutInfo)}.
     * In this flow the PinItemRequest is delivered to the caller app. Its the app's responsibility
     * to send it to the Launcher app (via {@link android.app.Activity#setResult(int, Intent)}).
     */
    public Intent createShortcutResultIntent(@NonNull ShortcutInfo inShortcut, int userId) {
        // Find the default launcher activity
        final int launcherUserId = mService.getParentOrSelfUserId(userId);
        final ComponentName defaultLauncher = mService.getDefaultLauncher(launcherUserId);
        if (defaultLauncher == null) {
            Log.e(TAG, "Default launcher not found.");
            return null;
        }

        // Make sure the launcher user is unlocked. (it's always the parent profile, so should
        // really be unlocked here though.)
        mService.throwIfUserLockedL(launcherUserId);

        // Next, validate the incoming shortcut, etc.
        final PinItemRequest request = requestPinShortcutLocked(inShortcut, null,
                Pair.create(defaultLauncher, launcherUserId));
        return new Intent().putExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST, request);
    }

    /**
     * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)}.
     */
    @NonNull
    private PinItemRequest requestPinShortcutLocked(ShortcutInfo inShortcut,
            IntentSender resultIntentOriginal, Pair<ComponentName, Integer> confirmActivity) {
        final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked(
                inShortcut.getPackage(), inShortcut.getUserId());

        final ShortcutInfo existing = ps.findShortcutById(inShortcut.getId());
        final boolean existsAlready = existing != null;

        if (DEBUG) {
            Slog.d(TAG, "requestPinnedShortcut: package=" + inShortcut.getPackage()
                    + " existsAlready=" + existsAlready
                    + " shortcut=" + inShortcut.toInsecureString());
        }

        // This is the shortcut that'll be sent to the launcher.
        final ShortcutInfo shortcutForLauncher;
        final String launcherPackage = confirmActivity.first.getPackageName();
        final int launcherUserId = confirmActivity.second;

        IntentSender resultIntentToSend = resultIntentOriginal;

        if (existsAlready) {
            validateExistingShortcut(existing);

            final boolean isAlreadyPinned = mService.getLauncherShortcutsLocked(
                    launcherPackage, existing.getUserId(), launcherUserId).hasPinned(existing);
            if (isAlreadyPinned) {
                // When the shortcut is already pinned by this launcher, the request will always
                // succeed, so just send the result at this point.
                sendResultIntent(resultIntentOriginal, null);

                // So, do not send the intent again.
                resultIntentToSend = null;
            }

            // Pass a clone, not the original.
            // Note this will remove the intent and icons.
            shortcutForLauncher = existing.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);

            if (!isAlreadyPinned) {
                // FLAG_PINNED may still be set, if it's pinned by other launchers.
                shortcutForLauncher.clearFlags(ShortcutInfo.FLAG_PINNED);
            }
        } else {
            // If the shortcut has no default activity, try to set the main activity.
            // But in the request-pin case, it's optional, so it's okay even if the caller
            // has no default activity.
            if (inShortcut.getActivity() == null) {
                inShortcut.setActivity(mService.injectGetDefaultMainActivity(
                        inShortcut.getPackage(), inShortcut.getUserId()));
            }

            // It doesn't exist, so it must have all mandatory fields.
            mService.validateShortcutForPinRequest(inShortcut);

            // Initialize the ShortcutInfo for pending approval.
            inShortcut.resolveResourceStrings(mService.injectGetResourcesForApplicationAsUser(
                    inShortcut.getPackage(), inShortcut.getUserId()));
            if (DEBUG) {
                Slog.d(TAG, "Resolved shortcut=" + inShortcut.toInsecureString());
            }
            // We should strip out the intent, but should preserve the icon.
            shortcutForLauncher = inShortcut.clone(
                    ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER_APPROVAL);
        }
        if (DEBUG) {
            Slog.d(TAG, "Sending to launcher=" + shortcutForLauncher.toInsecureString());
        }

        // Create a request object.
        final PinShortcutRequestInner inner =
                new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher,
                        resultIntentToSend, launcherPackage, launcherUserId,
                        mService.injectGetPackageUid(launcherPackage, launcherUserId),
                        existsAlready);

        return new PinItemRequest(inner, PinItemRequest.REQUEST_TYPE_SHORTCUT);
    }

    private void validateExistingShortcut(ShortcutInfo shortcutInfo) {
        // Make sure it's enabled.
        // (Because we can't always force enable it automatically as it may be a stale
        // manifest shortcut.)
        Preconditions.checkArgument(shortcutInfo.isEnabled(),
                "Shortcut ID=" + shortcutInfo + " already exists but disabled.");

    }

    private boolean startRequestConfirmActivity(ComponentName activity, int launcherUserId,
            PinItemRequest request, int requestType) {
        final String action = requestType == LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT ?
                LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT :
                LauncherApps.ACTION_CONFIRM_PIN_APPWIDGET;

        // Start the activity.
        final Intent confirmIntent = new Intent(action);
        confirmIntent.setComponent(activity);
        confirmIntent.putExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST, request);
        confirmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

        final long token = mService.injectClearCallingIdentity();
        try {
            mService.mContext.startActivityAsUser(
                    confirmIntent, UserHandle.of(launcherUserId));
        } catch (RuntimeException e) { // ActivityNotFoundException, etc.
            Log.e(TAG, "Unable to start activity " + activity, e);
            return false;
        } finally {
            mService.injectRestoreCallingIdentity(token);
        }
        return true;
    }

    /**
     * Find the activity that handles {@link LauncherApps#ACTION_CONFIRM_PIN_SHORTCUT} in the
     * default launcher.
     */
    @Nullable
    @VisibleForTesting
    Pair<ComponentName, Integer> getRequestPinConfirmationActivity(
            int callingUserId, int requestType) {
        // Find the default launcher.
        final int launcherUserId = mService.getParentOrSelfUserId(callingUserId);
        final ComponentName defaultLauncher = mService.getDefaultLauncher(launcherUserId);

        if (defaultLauncher == null) {
            Log.e(TAG, "Default launcher not found.");
            return null;
        }
        final ComponentName activity = mService.injectGetPinConfirmationActivity(
                defaultLauncher.getPackageName(), launcherUserId, requestType);
        return (activity == null) ? null : Pair.create(activity, launcherUserId);
    }

    public void sendResultIntent(@Nullable IntentSender intent, @Nullable Intent extras) {
        if (DEBUG) {
            Slog.d(TAG, "Sending result intent.");
        }
        mService.injectSendIntentSender(intent, extras);
    }

    public boolean isCallerUid(int uid) {
        return uid == mService.injectBinderCallingUid();
    }

    /**
     * The last step of the "request pin shortcut" flow.  Called when the launcher accepted a
     * request.
     */
    public boolean directPinShortcut(PinShortcutRequestInner request) {

        final ShortcutInfo original = request.shortcutOriginal;
        final int appUserId = original.getUserId();
        final String appPackageName = original.getPackage();
        final int launcherUserId = request.launcherUserId;
        final String launcherPackage = request.launcherPackage;
        final String shortcutId = original.getId();

        synchronized (mLock) {
            if (!(mService.isUserUnlockedL(appUserId)
                    && mService.isUserUnlockedL(request.launcherUserId))) {
                Log.w(TAG, "User is locked now.");
                return false;
            }

            final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked(
                    launcherPackage, appUserId, launcherUserId);
            launcher.attemptToRestoreIfNeededAndSave();
            if (launcher.hasPinned(original)) {
                if (DEBUG) {
                    Slog.d(TAG, "Shortcut " + original + " already pinned.");
                }
                return true;
            }

            final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked(
                    appPackageName, appUserId);
            final ShortcutInfo current = ps.findShortcutById(shortcutId);

            // The shortcut might have been changed, so we need to do the same validation again.
            try {
                if (current == null) {
                    // It doesn't exist, so it must have all necessary fields.
                    mService.validateShortcutForPinRequest(original);
                } else {
                    validateExistingShortcut(current);
                }
            } catch (RuntimeException e) {
                Log.w(TAG, "Unable to pin shortcut: " + e.getMessage());
                return false;
            }

            // If the shortcut doesn't exist, need to create it.
            // First, create it as a dynamic shortcut.
            if (current == null) {
                if (DEBUG) {
                    Slog.d(TAG, "Temporarily adding " + shortcutId + " as dynamic");
                }
                // Add as a dynamic shortcut.  In order for a shortcut to be dynamic, it must
                // have a target activity, so we set a dummy here.  It's later removed
                // in deleteDynamicWithId().
                if (original.getActivity() == null) {
                    original.setActivity(mService.getDummyMainActivity(appPackageName));
                }
                ps.addOrUpdateDynamicShortcut(original);
            }

            // Pin the shortcut.
            if (DEBUG) {
                Slog.d(TAG, "Pinning " + shortcutId);
            }

            launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId);

            if (current == null) {
                if (DEBUG) {
                    Slog.d(TAG, "Removing " + shortcutId + " as dynamic");
                }
                ps.deleteDynamicWithId(shortcutId);
            }

            ps.adjustRanks(); // Shouldn't be needed, but just in case.
        }

        mService.verifyStates();
        mService.packageShortcutsChanged(appPackageName, appUserId);

        return true;
    }
}
