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

import static android.app.ActivityManager.START_SUCCESS;

import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.TimeUtils;

import com.android.internal.os.IResultReceiver;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.wm.SafeActivityOptions;

import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.Objects;

public final class PendingIntentRecord extends IIntentSender.Stub {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM;

    public static final int FLAG_ACTIVITY_SENDER = 1 << 0;
    public static final int FLAG_BROADCAST_SENDER = 1 << 1;
    public static final int FLAG_SERVICE_SENDER = 1 << 2;

    final PendingIntentController controller;
    final Key key;
    final int uid;
    public final WeakReference<PendingIntentRecord> ref;
    boolean sent = false;
    boolean canceled = false;
    private ArrayMap<IBinder, Long> whitelistDuration;
    private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
    private ArraySet<IBinder> mAllowBgActivityStartsForActivitySender = new ArraySet<>();
    private ArraySet<IBinder> mAllowBgActivityStartsForBroadcastSender = new ArraySet<>();
    private ArraySet<IBinder> mAllowBgActivityStartsForServiceSender = new ArraySet<>();

    String stringName;
    String lastTagPrefix;
    String lastTag;

    final static class Key {
        final int type;
        final String packageName;
        final String featureId;
        final IBinder activity;
        final String who;
        final int requestCode;
        final Intent requestIntent;
        final String requestResolvedType;
        final SafeActivityOptions options;
        Intent[] allIntents;
        String[] allResolvedTypes;
        final int flags;
        final int hashCode;
        final int userId;

        private static final int ODD_PRIME_NUMBER = 37;

        Key(int _t, String _p, @Nullable String _featureId, IBinder _a, String _w,
                int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId) {
            type = _t;
            packageName = _p;
            featureId = _featureId;
            activity = _a;
            who = _w;
            requestCode = _r;
            requestIntent = _i != null ? _i[_i.length-1] : null;
            requestResolvedType = _it != null ? _it[_it.length-1] : null;
            allIntents = _i;
            allResolvedTypes = _it;
            flags = _f;
            options = _o;
            userId = _userId;

            int hash = 23;
            hash = (ODD_PRIME_NUMBER*hash) + _f;
            hash = (ODD_PRIME_NUMBER*hash) + _r;
            hash = (ODD_PRIME_NUMBER*hash) + _userId;
            if (_w != null) {
                hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
            }
            if (_a != null) {
                hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode();
            }
            if (requestIntent != null) {
                hash = (ODD_PRIME_NUMBER*hash) + requestIntent.filterHashCode();
            }
            if (requestResolvedType != null) {
                hash = (ODD_PRIME_NUMBER*hash) + requestResolvedType.hashCode();
            }
            hash = (ODD_PRIME_NUMBER*hash) + (_p != null ? _p.hashCode() : 0);
            hash = (ODD_PRIME_NUMBER*hash) + _t;
            hashCode = hash;
            //Slog.i(ActivityManagerService.TAG, this + " hashCode=0x"
            //        + Integer.toHexString(hashCode));
        }

        @Override
        public boolean equals(Object otherObj) {
            if (otherObj == null) {
                return false;
            }
            try {
                Key other = (Key)otherObj;
                if (type != other.type) {
                    return false;
                }
                if (userId != other.userId){
                    return false;
                }
                if (!Objects.equals(packageName, other.packageName)) {
                    return false;
                }
                if (!Objects.equals(featureId, other.featureId)) {
                    return false;
                }
                if (activity != other.activity) {
                    return false;
                }
                if (!Objects.equals(who, other.who)) {
                    return false;
                }
                if (requestCode != other.requestCode) {
                    return false;
                }
                if (requestIntent != other.requestIntent) {
                    if (requestIntent != null) {
                        if (!requestIntent.filterEquals(other.requestIntent)) {
                            return false;
                        }
                    } else if (other.requestIntent != null) {
                        return false;
                    }
                }
                if (!Objects.equals(requestResolvedType, other.requestResolvedType)) {
                    return false;
                }
                if (flags != other.flags) {
                    return false;
                }
                return true;
            } catch (ClassCastException e) {
            }
            return false;
        }

        public int hashCode() {
            return hashCode;
        }

        public String toString() {
            return "Key{" + typeName()
                + " pkg=" + packageName + (featureId != null ? "/" + featureId : "")
                + " intent="
                + (requestIntent != null
                        ? requestIntent.toShortString(false, true, false, false) : "<null>")
                + " flags=0x" + Integer.toHexString(flags) + " u=" + userId + "}";
        }

        String typeName() {
            switch (type) {
                case ActivityManager.INTENT_SENDER_ACTIVITY:
                    return "startActivity";
                case ActivityManager.INTENT_SENDER_BROADCAST:
                    return "broadcastIntent";
                case ActivityManager.INTENT_SENDER_SERVICE:
                    return "startService";
                case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
                    return "startForegroundService";
                case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
                    return "activityResult";
            }
            return Integer.toString(type);
        }
    }

    PendingIntentRecord(PendingIntentController _controller, Key _k, int _u) {
        controller = _controller;
        key = _k;
        uid = _u;
        ref = new WeakReference<>(this);
    }

    void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
        if (duration > 0) {
            if (whitelistDuration == null) {
                whitelistDuration = new ArrayMap<>();
            }
            whitelistDuration.put(whitelistToken, duration);
        } else if (whitelistDuration != null) {
            whitelistDuration.remove(whitelistToken);
            if (whitelistDuration.size() <= 0) {
                whitelistDuration = null;
            }

        }
        this.stringName = null;
    }

    void setAllowBgActivityStarts(IBinder token, int flags) {
        if (token == null) return;
        if ((flags & FLAG_ACTIVITY_SENDER) != 0) {
            mAllowBgActivityStartsForActivitySender.add(token);
        }
        if ((flags & FLAG_BROADCAST_SENDER) != 0) {
            mAllowBgActivityStartsForBroadcastSender.add(token);
        }
        if ((flags & FLAG_SERVICE_SENDER) != 0) {
            mAllowBgActivityStartsForServiceSender.add(token);
        }
    }

    void clearAllowBgActivityStarts(IBinder token) {
        if (token == null) return;
        mAllowBgActivityStartsForActivitySender.remove(token);
        mAllowBgActivityStartsForBroadcastSender.remove(token);
        mAllowBgActivityStartsForServiceSender.remove(token);
    }

    public void registerCancelListenerLocked(IResultReceiver receiver) {
        if (mCancelCallbacks == null) {
            mCancelCallbacks = new RemoteCallbackList<>();
        }
        mCancelCallbacks.register(receiver);
    }

    public void unregisterCancelListenerLocked(IResultReceiver receiver) {
        if (mCancelCallbacks == null) {
            return; // Already unregistered or detached.
        }
        mCancelCallbacks.unregister(receiver);
        if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
            mCancelCallbacks = null;
        }
    }

    public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() {
        RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks;
        mCancelCallbacks = null;
        return listeners;
    }

    public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
            IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
        sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
                requiredPermission, null, null, 0, 0, 0, options);
    }

    public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken,
            IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
        return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
                requiredPermission, null, null, 0, 0, 0, options);
    }

    public int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
            IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo,
            String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) {
        if (intent != null) intent.setDefusable(true);
        if (options != null) options.setDefusable(true);

        Long duration = null;
        Intent finalIntent = null;
        Intent[] allIntents = null;
        String[] allResolvedTypes = null;
        SafeActivityOptions mergedOptions = null;
        synchronized (controller.mLock) {
            if (canceled) {
                return ActivityManager.START_CANCELED;
            }

            sent = true;
            if ((key.flags & PendingIntent.FLAG_ONE_SHOT) != 0) {
                controller.cancelIntentSender(this, true);
            }

            finalIntent = key.requestIntent != null ? new Intent(key.requestIntent) : new Intent();

            final boolean immutable = (key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
            if (!immutable) {
                if (intent != null) {
                    int changes = finalIntent.fillIn(intent, key.flags);
                    if ((changes & Intent.FILL_IN_DATA) == 0) {
                        resolvedType = key.requestResolvedType;
                    }
                } else {
                    resolvedType = key.requestResolvedType;
                }
                flagsMask &= ~Intent.IMMUTABLE_FLAGS;
                flagsValues &= flagsMask;
                finalIntent.setFlags((finalIntent.getFlags() & ~flagsMask) | flagsValues);
            } else {
                resolvedType = key.requestResolvedType;
            }

            // Apply any launch flags from the ActivityOptions. This is to ensure that the caller
            // can specify a consistent launch mode even if the PendingIntent is immutable
            final ActivityOptions opts = ActivityOptions.fromBundle(options);
            if (opts != null) {
                finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
            }

            // Extract options before clearing calling identity
            mergedOptions = key.options;
            if (mergedOptions == null) {
                mergedOptions = new SafeActivityOptions(opts);
            } else {
                mergedOptions.setCallerOptions(opts);
            }

            if (whitelistDuration != null) {
                duration = whitelistDuration.get(whitelistToken);
            }

            if (key.type == ActivityManager.INTENT_SENDER_ACTIVITY
                    && key.allIntents != null && key.allIntents.length > 1) {
                // Copy all intents and resolved types while we have the controller lock so we can
                // use it later when the lock isn't held.
                allIntents = new Intent[key.allIntents.length];
                allResolvedTypes = new String[key.allIntents.length];
                System.arraycopy(key.allIntents, 0, allIntents, 0, key.allIntents.length);
                if (key.allResolvedTypes != null) {
                    System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
                            key.allResolvedTypes.length);
                }
                allIntents[allIntents.length - 1] = finalIntent;
                allResolvedTypes[allResolvedTypes.length - 1] = resolvedType;
            }

        }
        // We don't hold the controller lock beyond this point as we will be calling into AM and WM.

        final int callingUid = Binder.getCallingUid();
        final int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();

        int res = START_SUCCESS;
        try {
            if (duration != null) {
                int procState = controller.mAmInternal.getUidProcessState(callingUid);
                if (!ActivityManager.isProcStateBackground(procState)) {
                    StringBuilder tag = new StringBuilder(64);
                    tag.append("pendingintent:");
                    UserHandle.formatUid(tag, callingUid);
                    tag.append(":");
                    if (finalIntent.getAction() != null) {
                        tag.append(finalIntent.getAction());
                    } else if (finalIntent.getComponent() != null) {
                        finalIntent.getComponent().appendShortString(tag);
                    } else if (finalIntent.getData() != null) {
                        tag.append(finalIntent.getData().toSafeString());
                    }
                    controller.mAmInternal.tempWhitelistForPendingIntent(callingPid, callingUid,
                            uid, duration, tag.toString());
                } else {
                    Slog.w(TAG, "Not doing whitelist " + this + ": caller state=" + procState);
                }
            }

            boolean sendFinish = finishedReceiver != null;
            int userId = key.userId;
            if (userId == UserHandle.USER_CURRENT) {
                userId = controller.mUserController.getCurrentOrTargetUserId();
            }
            // temporarily allow receivers and services to open activities from background if the
            // PendingIntent.send() caller was foreground at the time of sendInner() call
            final boolean allowTrampoline = uid != callingUid
                    && controller.mAtmInternal.isUidForeground(callingUid);

            // note: we on purpose don't pass in the information about the PendingIntent's creator,
            // like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because
            // it's not unusual for the creator's process to not be alive at this time
            switch (key.type) {
                case ActivityManager.INTENT_SENDER_ACTIVITY:
                    try {
                        // Note when someone has a pending intent, even from different
                        // users, then there's no need to ensure the calling user matches
                        // the target user, so validateIncomingUser is always false below.

                        if (key.allIntents != null && key.allIntents.length > 1) {
                            res = controller.mAtmInternal.startActivitiesInPackage(
                                    uid, callingPid, callingUid, key.packageName, key.featureId,
                                    allIntents, allResolvedTypes, resultTo, mergedOptions, userId,
                                    false /* validateIncomingUser */,
                                    this /* originatingPendingIntent */,
                                    mAllowBgActivityStartsForActivitySender.contains(whitelistToken));
                        } else {
                            res = controller.mAtmInternal.startActivityInPackage(uid, callingPid,
                                    callingUid, key.packageName, key.featureId, finalIntent,
                                    resolvedType, resultTo, resultWho, requestCode, 0,
                                    mergedOptions, userId, null, "PendingIntentRecord",
                                    false /* validateIncomingUser */,
                                    this /* originatingPendingIntent */,
                                    mAllowBgActivityStartsForActivitySender.contains(
                                            whitelistToken));
                        }
                    } catch (RuntimeException e) {
                        Slog.w(TAG, "Unable to send startActivity intent", e);
                    }
                    break;
                case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
                    controller.mAtmInternal.sendActivityResult(-1, key.activity, key.who,
                                key.requestCode, code, finalIntent);
                    break;
                case ActivityManager.INTENT_SENDER_BROADCAST:
                    try {
                        // If a completion callback has been requested, require
                        // that the broadcast be delivered synchronously
                        int sent = controller.mAmInternal.broadcastIntentInPackage(key.packageName,
                                key.featureId, uid, callingUid, callingPid, finalIntent,
                                resolvedType, finishedReceiver, code, null, null,
                                requiredPermission, options, (finishedReceiver != null), false,
                                userId,
                                mAllowBgActivityStartsForBroadcastSender.contains(whitelistToken)
                                        || allowTrampoline);
                        if (sent == ActivityManager.BROADCAST_SUCCESS) {
                            sendFinish = false;
                        }
                    } catch (RuntimeException e) {
                        Slog.w(TAG, "Unable to send startActivity intent", e);
                    }
                    break;
                case ActivityManager.INTENT_SENDER_SERVICE:
                case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
                    try {
                        controller.mAmInternal.startServiceInPackage(uid, finalIntent, resolvedType,
                                key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE,
                                key.packageName, key.featureId, userId,
                                mAllowBgActivityStartsForServiceSender.contains(whitelistToken)
                                || allowTrampoline);
                    } catch (RuntimeException e) {
                        Slog.w(TAG, "Unable to send startService intent", e);
                    } catch (TransactionTooLargeException e) {
                        res = ActivityManager.START_CANCELED;
                    }
                    break;
            }

            if (sendFinish && res != ActivityManager.START_CANCELED) {
                try {
                    finishedReceiver.performReceive(new Intent(finalIntent), 0,
                            null, null, false, false, key.userId);
                } catch (RemoteException e) {
                }
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }

        return res;
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (!canceled) {
                controller.mH.sendMessage(PooledLambda.obtainMessage(
                        PendingIntentRecord::completeFinalize, this));
            }
        } finally {
            super.finalize();
        }
    }

    private void completeFinalize() {
        synchronized(controller.mLock) {
            WeakReference<PendingIntentRecord> current = controller.mIntentSenderRecords.get(key);
            if (current == ref) {
                controller.mIntentSenderRecords.remove(key);
            }
        }
    }

    public void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("uid="); pw.print(uid);
                pw.print(" packageName="); pw.print(key.packageName);
                pw.print(" featureId="); pw.print(key.featureId);
                pw.print(" type="); pw.print(key.typeName());
                pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
        if (key.activity != null || key.who != null) {
            pw.print(prefix); pw.print("activity="); pw.print(key.activity);
                    pw.print(" who="); pw.println(key.who);
        }
        if (key.requestCode != 0 || key.requestResolvedType != null) {
            pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
                    pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
        }
        if (key.requestIntent != null) {
            pw.print(prefix); pw.print("requestIntent=");
                    pw.println(key.requestIntent.toShortString(false, true, true, false));
        }
        if (sent || canceled) {
            pw.print(prefix); pw.print("sent="); pw.print(sent);
                    pw.print(" canceled="); pw.println(canceled);
        }
        if (whitelistDuration != null) {
            pw.print(prefix);
            pw.print("whitelistDuration=");
            for (int i = 0; i < whitelistDuration.size(); i++) {
                if (i != 0) {
                    pw.print(", ");
                }
                pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
                pw.print(":");
                TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
            }
            pw.println();
        }
        if (mCancelCallbacks != null) {
            pw.print(prefix); pw.println("mCancelCallbacks:");
            for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) {
                pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": ");
                pw.println(mCancelCallbacks.getRegisteredCallbackItem(i));
            }
        }
    }

    public String toString() {
        if (stringName != null) {
            return stringName;
        }
        StringBuilder sb = new StringBuilder(128);
        sb.append("PendingIntentRecord{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
        sb.append(' ');
        sb.append(key.packageName);
        if (key.featureId != null) {
            sb.append('/');
            sb.append(key.featureId);
        }
        sb.append(' ');
        sb.append(key.typeName());
        if (whitelistDuration != null) {
            sb.append( " (whitelist: ");
            for (int i = 0; i < whitelistDuration.size(); i++) {
                if (i != 0) {
                    sb.append(",");
                }
                sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
                sb.append(":");
                TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
            }
            sb.append(")");
        }
        sb.append('}');
        return stringName = sb.toString();
    }
}
