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

import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.IVoiceInteractionSessionService;
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionSession;
import android.util.Slog;
import android.view.IWindowManager;
import android.view.WindowManager;

import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.IResultReceiver;
import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

final class VoiceInteractionSessionConnection implements ServiceConnection {

    final static String TAG = "VoiceInteractionServiceManager";

    private static final String KEY_RECEIVER_EXTRA_COUNT = "count";
    private static final String KEY_RECEIVER_EXTRA_INDEX = "index";

    final IBinder mToken = new Binder();
    final Object mLock;
    final ComponentName mSessionComponentName;
    final Intent mBindIntent;
    final int mUser;
    final Context mContext;
    final Callback mCallback;
    final int mCallingUid;
    final Handler mHandler;
    final IActivityManager mAm;
    final IWindowManager mIWindowManager;
    final AppOpsManager mAppOps;
    final IBinder mPermissionOwner;
    boolean mShown;
    Bundle mShowArgs;
    int mShowFlags;
    boolean mBound;
    boolean mFullyBound;
    boolean mCanceled;
    IVoiceInteractionSessionService mService;
    IVoiceInteractionSession mSession;
    IVoiceInteractor mInteractor;
    boolean mHaveAssistData;
    int mPendingAssistDataCount;
    ArrayList<AssistDataForActivity> mAssistData = new ArrayList<>();
    boolean mHaveScreenshot;
    Bitmap mScreenshot;
    ArrayList<IVoiceInteractionSessionShowCallback> mPendingShowCallbacks = new ArrayList<>();

    static class AssistDataForActivity {
        int activityIndex;
        int activityCount;
        Bundle data;

        public AssistDataForActivity(Bundle data) {
            this.data = data;
            Bundle receiverExtras = data.getBundle(VoiceInteractionSession.KEY_RECEIVER_EXTRAS);
            if (receiverExtras != null) {
                activityIndex = receiverExtras.getInt(KEY_RECEIVER_EXTRA_INDEX);
                activityCount = receiverExtras.getInt(KEY_RECEIVER_EXTRA_COUNT);
            }
        }
    }

    IVoiceInteractionSessionShowCallback mShowCallback =
            new IVoiceInteractionSessionShowCallback.Stub() {
        @Override
        public void onFailed() throws RemoteException {
            synchronized (mLock) {
                notifyPendingShowCallbacksFailedLocked();
            }
        }

        @Override
        public void onShown() throws RemoteException {
            synchronized (mLock) {
                // TODO: Figure out whether this is good enough or whether we need to hook into
                // Window manager to actually wait for the window to be drawn.
                notifyPendingShowCallbacksShownLocked();
            }
        }
    };

    public interface Callback {
        public void sessionConnectionGone(VoiceInteractionSessionConnection connection);
    }

    final ServiceConnection mFullConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

    final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
        @Override
        public void send(int resultCode, Bundle resultData) throws RemoteException {
            synchronized (mLock) {
                if (mShown) {
                    mHaveAssistData = true;
                    mAssistData.add(new AssistDataForActivity(resultData));
                    deliverSessionDataLocked();
                }
            }
        }
    };

    final IAssistScreenshotReceiver mScreenshotReceiver = new IAssistScreenshotReceiver.Stub() {
        @Override
        public void send(Bitmap screenshot) throws RemoteException {
            synchronized (mLock) {
                if (mShown) {
                    mHaveScreenshot = true;
                    mScreenshot = screenshot;
                    deliverSessionDataLocked();
                }
            }
        }
    };

    public VoiceInteractionSessionConnection(Object lock, ComponentName component, int user,
            Context context, Callback callback, int callingUid, Handler handler) {
        mLock = lock;
        mSessionComponentName = component;
        mUser = user;
        mContext = context;
        mCallback = callback;
        mCallingUid = callingUid;
        mHandler = handler;
        mAm = ActivityManagerNative.getDefault();
        mIWindowManager = IWindowManager.Stub.asInterface(
                ServiceManager.getService(Context.WINDOW_SERVICE));
        mAppOps = context.getSystemService(AppOpsManager.class);
        IBinder permOwner = null;
        try {
            permOwner = mAm.newUriPermissionOwner("voicesession:"
                    + component.flattenToShortString());
        } catch (RemoteException e) {
            Slog.w("voicesession", "AM dead", e);
        }
        mPermissionOwner = permOwner;
        mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
        mBindIntent.setComponent(mSessionComponentName);
        mBound = mContext.bindServiceAsUser(mBindIntent, this,
                Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
                        | Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser));
        if (mBound) {
            try {
                mIWindowManager.addWindowToken(mToken,
                        WindowManager.LayoutParams.TYPE_VOICE_INTERACTION);
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed adding window token", e);
            }
        } else {
            Slog.w(TAG, "Failed binding to voice interaction session service "
                    + mSessionComponentName);
        }
    }

    public int getUserDisabledShowContextLocked() {
        int flags = 0;
        if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) == 0) {
            flags |= VoiceInteractionSession.SHOW_WITH_ASSIST;
        }
        if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1, mUser) == 0) {
            flags |= VoiceInteractionSession.SHOW_WITH_SCREENSHOT;
        }
        return flags;
    }

    public boolean showLocked(Bundle args, int flags, int disabledContext,
            IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken,
            List<IBinder> topActivities) {
        if (mBound) {
            if (!mFullyBound) {
                mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
                        Context.BIND_AUTO_CREATE | Context.BIND_TREAT_LIKE_ACTIVITY
                                | Context.BIND_FOREGROUND_SERVICE,
                        new UserHandle(mUser));
            }
            mShown = true;
            boolean isAssistDataAllowed = true;
            try {
                isAssistDataAllowed = mAm.isAssistDataAllowedOnCurrentActivity();
            } catch (RemoteException e) {
            }
            disabledContext |= getUserDisabledShowContextLocked();
            boolean structureEnabled = isAssistDataAllowed
                    && (disabledContext&VoiceInteractionSession.SHOW_WITH_ASSIST) == 0;
            boolean screenshotEnabled = isAssistDataAllowed && structureEnabled
                    && (disabledContext&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) == 0;
            mShowArgs = args;
            mShowFlags = flags;
            mHaveAssistData = false;
            mPendingAssistDataCount = 0;
            boolean needDisclosure = false;
            if ((flags&VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) {
                if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid,
                        mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
                        && structureEnabled) {
                    mAssistData.clear();
                    final int count = activityToken != null ? 1 : topActivities.size();
                    // Temp workaround for bug: 28348867  Revert after DP3
                    for (int i = 0; i < count && i < 1; i++) {
                        IBinder topActivity = count == 1 ? activityToken : topActivities.get(i);
                        try {
                            MetricsLogger.count(mContext, "assist_with_context", 1);
                            Bundle receiverExtras = new Bundle();
                            receiverExtras.putInt(KEY_RECEIVER_EXTRA_INDEX, i);
                            receiverExtras.putInt(KEY_RECEIVER_EXTRA_COUNT, count);
                            if (mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
                                    mAssistReceiver, receiverExtras, topActivity,
                                    /* focused= */ i == 0, /* newSessionId= */ i == 0)) {
                                needDisclosure = true;
                                mPendingAssistDataCount++;
                            } else if (i == 0) {
                                // Wasn't allowed... given that, let's not do the screenshot either.
                                mHaveAssistData = true;
                                mAssistData.clear();
                                screenshotEnabled = false;
                                break;
                            }
                        } catch (RemoteException e) {
                        }
                    }
                } else {
                    mHaveAssistData = true;
                    mAssistData.clear();
                }
            } else {
                mAssistData.clear();
            }
            mHaveScreenshot = false;
            if ((flags&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0) {
                if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_SCREENSHOT, mCallingUid,
                        mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
                        && screenshotEnabled) {
                    try {
                        MetricsLogger.count(mContext, "assist_with_screen", 1);
                        needDisclosure = true;
                        mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
                    } catch (RemoteException e) {
                    }
                } else {
                    mHaveScreenshot = true;
                    mScreenshot = null;
                }
            } else {
                mScreenshot = null;
            }
            if (needDisclosure) {
                mHandler.post(mShowAssistDisclosureRunnable);
            }
            if (mSession != null) {
                try {
                    mSession.show(mShowArgs, mShowFlags, showCallback);
                    mShowArgs = null;
                    mShowFlags = 0;
                } catch (RemoteException e) {
                }
                deliverSessionDataLocked();
            } else if (showCallback != null) {
                mPendingShowCallbacks.add(showCallback);
            }
            return true;
        }
        if (showCallback != null) {
            try {
                showCallback.onFailed();
            } catch (RemoteException e) {
            }
        }
        return false;
    }

    void grantUriPermission(Uri uri, int mode, int srcUid, int destUid, String destPkg) {
        if (!"content".equals(uri.getScheme())) {
            return;
        }
        long ident = Binder.clearCallingIdentity();
        try {
            // This will throw SecurityException for us.
            mAm.checkGrantUriPermission(srcUid, null, ContentProvider.getUriWithoutUserId(uri),
                    mode, ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(srcUid)));
            // No security exception, do the grant.
            int sourceUserId = ContentProvider.getUserIdFromUri(uri, mUser);
            uri = ContentProvider.getUriWithoutUserId(uri);
            mAm.grantUriPermissionFromOwner(mPermissionOwner, srcUid, destPkg,
                    uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, mUser);
        } catch (RemoteException e) {
        } catch (SecurityException e) {
            Slog.w(TAG, "Can't propagate permission", e);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }

    }

    void grantClipDataItemPermission(ClipData.Item item, int mode, int srcUid, int destUid,
            String destPkg) {
        if (item.getUri() != null) {
            grantUriPermission(item.getUri(), mode, srcUid, destUid, destPkg);
        }
        Intent intent = item.getIntent();
        if (intent != null && intent.getData() != null) {
            grantUriPermission(intent.getData(), mode, srcUid, destUid, destPkg);
        }
    }

    void grantClipDataPermissions(ClipData data, int mode, int srcUid, int destUid,
            String destPkg) {
        final int N = data.getItemCount();
        for (int i=0; i<N; i++) {
            grantClipDataItemPermission(data.getItemAt(i), mode, srcUid, destUid, destPkg);
        }
    }

    void deliverSessionDataLocked() {
        if (mSession == null) {
            return;
        }
        if (mHaveAssistData) {
            AssistDataForActivity assistData;
            if (mAssistData.isEmpty()) {
                // We're not actually going to get any data, deliver some nothing
                try {
                    mSession.handleAssist(null, null, null, 0, 0);
                } catch (RemoteException e) {
                }
            } else {
                while (!mAssistData.isEmpty()) {
                    if (mPendingAssistDataCount <= 0) {
                        Slog.e(TAG, "mPendingAssistDataCount is " + mPendingAssistDataCount);
                    }
                    mPendingAssistDataCount--;
                    assistData = mAssistData.remove(0);
                    if (assistData.data == null) {
                        try {
                            mSession.handleAssist(null, null, null, assistData.activityIndex,
                                    assistData.activityCount);
                        } catch (RemoteException e) {
                        }
                    } else {
                        deliverSessionDataLocked(assistData);
                    }
                }
            }
            if (mPendingAssistDataCount <= 0) {
                mHaveAssistData = false;
            } // else, more to come
        }
        if (mHaveScreenshot) {
            try {
                mSession.handleScreenshot(mScreenshot);
            } catch (RemoteException e) {
            }
            mScreenshot = null;
            mHaveScreenshot = false;
        }
    }

    private void deliverSessionDataLocked(AssistDataForActivity assistDataForActivity) {
        Bundle assistData = assistDataForActivity.data.getBundle(
                VoiceInteractionSession.KEY_DATA);
        AssistStructure structure = assistDataForActivity.data.getParcelable(
                VoiceInteractionSession.KEY_STRUCTURE);
        AssistContent content = assistDataForActivity.data.getParcelable(
                VoiceInteractionSession.KEY_CONTENT);
        int uid = assistDataForActivity.data.getInt(Intent.EXTRA_ASSIST_UID, -1);
        if (uid >= 0 && content != null) {
            Intent intent = content.getIntent();
            if (intent != null) {
                ClipData data = intent.getClipData();
                if (data != null && Intent.isAccessUriMode(intent.getFlags())) {
                    grantClipDataPermissions(data, intent.getFlags(), uid,
                            mCallingUid, mSessionComponentName.getPackageName());
                }
            }
            ClipData data = content.getClipData();
            if (data != null) {
                grantClipDataPermissions(data,
                        Intent.FLAG_GRANT_READ_URI_PERMISSION,
                        uid, mCallingUid, mSessionComponentName.getPackageName());
            }
        }
        try {
            mSession.handleAssist(assistData, structure, content,
                    assistDataForActivity.activityIndex, assistDataForActivity.activityCount);
        } catch (RemoteException e) {
        }
    }

    public boolean hideLocked() {
        if (mBound) {
            if (mShown) {
                mShown = false;
                mShowArgs = null;
                mShowFlags = 0;
                mHaveAssistData = false;
                mAssistData.clear();
                if (mSession != null) {
                    try {
                        mSession.hide();
                    } catch (RemoteException e) {
                    }
                }
                try {
                    mAm.revokeUriPermissionFromOwner(mPermissionOwner, null,
                            Intent.FLAG_GRANT_READ_URI_PERMISSION
                                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
                            mUser);
                } catch (RemoteException e) {
                }
                if (mSession != null) {
                    try {
                        mAm.finishVoiceTask(mSession);
                    } catch (RemoteException e) {
                    }
                }
            }
            if (mFullyBound) {
                mContext.unbindService(mFullConnection);
                mFullyBound = false;
            }
            return true;
        }
        return false;
    }

    public void cancelLocked(boolean finishTask) {
        hideLocked();
        mCanceled = true;
        if (mBound) {
            if (mSession != null) {
                try {
                    mSession.destroy();
                } catch (RemoteException e) {
                    Slog.w(TAG, "Voice interation session already dead");
                }
            }
            if (finishTask && mSession != null) {
                try {
                    mAm.finishVoiceTask(mSession);
                } catch (RemoteException e) {
                }
            }
            mContext.unbindService(this);
            try {
                mIWindowManager.removeWindowToken(mToken);
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed removing window token", e);
            }
            mBound = false;
            mService = null;
            mSession = null;
            mInteractor = null;
        }
        if (mFullyBound) {
            mContext.unbindService(mFullConnection);
            mFullyBound = false;
        }
    }

    public boolean deliverNewSessionLocked(IVoiceInteractionSession session,
            IVoiceInteractor interactor) {
        mSession = session;
        mInteractor = interactor;
        if (mShown) {
            try {
                session.show(mShowArgs, mShowFlags, mShowCallback);
                mShowArgs = null;
                mShowFlags = 0;
            } catch (RemoteException e) {
            }
            deliverSessionDataLocked();
        }
        return true;
    }

    private void notifyPendingShowCallbacksShownLocked() {
        for (int i = 0; i < mPendingShowCallbacks.size(); i++) {
            try {
                mPendingShowCallbacks.get(i).onShown();
            } catch (RemoteException e) {
            }
        }
        mPendingShowCallbacks.clear();
    }

    private void notifyPendingShowCallbacksFailedLocked() {
        for (int i = 0; i < mPendingShowCallbacks.size(); i++) {
            try {
                mPendingShowCallbacks.get(i).onFailed();
            } catch (RemoteException e) {
            }
        }
        mPendingShowCallbacks.clear();
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        synchronized (mLock) {
            mService = IVoiceInteractionSessionService.Stub.asInterface(service);
            if (!mCanceled) {
                try {
                    mService.newSession(mToken, mShowArgs, mShowFlags);
                } catch (RemoteException e) {
                    Slog.w(TAG, "Failed adding window token", e);
                }
            }
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mCallback.sessionConnectionGone(this);
        mService = null;
    }

    public void dump(String prefix, PrintWriter pw) {
        pw.print(prefix); pw.print("mToken="); pw.println(mToken);
        pw.print(prefix); pw.print("mShown="); pw.println(mShown);
        pw.print(prefix); pw.print("mShowArgs="); pw.println(mShowArgs);
        pw.print(prefix); pw.print("mShowFlags=0x"); pw.println(Integer.toHexString(mShowFlags));
        pw.print(prefix); pw.print("mBound="); pw.println(mBound);
        if (mBound) {
            pw.print(prefix); pw.print("mService="); pw.println(mService);
            pw.print(prefix); pw.print("mSession="); pw.println(mSession);
            pw.print(prefix); pw.print("mInteractor="); pw.println(mInteractor);
        }
        pw.print(prefix); pw.print("mHaveAssistData="); pw.println(mHaveAssistData);
        if (mHaveAssistData) {
            pw.print(prefix); pw.print("mAssistData="); pw.println(mAssistData);
        }
    }

    private Runnable mShowAssistDisclosureRunnable = new Runnable() {
        @Override
        public void run() {
            StatusBarManagerInternal statusBarInternal = LocalServices.getService(
                    StatusBarManagerInternal.class);
            if (statusBarInternal != null) {
                statusBarInternal.showAssistDisclosure();
            }
        }
    };
};
