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

import android.app.IInstrumentationWatcher;
import android.app.IUiAutomationConnection;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.util.PrintWriterPrinter;
import android.util.proto.ProtoOutputStream;

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

class ActiveInstrumentation {
    final ActivityManagerService mService;

    // Class installed to instrument app
    ComponentName mClass;

    // All process names that should be instrumented
    String[] mTargetProcesses;

    // The application being instrumented
    ApplicationInfo mTargetInfo;

    // Whether the application is instrumented as an sdk running in the sdk_sandbox.
    boolean mIsSdkInSandbox;

    // Where to save profiling
    String mProfileFile;

    // Who is waiting
    IInstrumentationWatcher mWatcher;

    // Connection to use the UI introspection APIs.
    IUiAutomationConnection mUiAutomationConnection;

    // Whether the caller holds START_ACTIVITIES_FROM_BACKGROUND permission
    boolean mHasBackgroundActivityStartsPermission;

    // Whether the caller holds START_FOREGROUND_SERVICES_FROM_BACKGROUND permission
    boolean mHasBackgroundForegroundServiceStartsPermission;

    // As given to us
    Bundle mArguments;

    // Any intermediate results that have been collected.
    Bundle mCurResults;

    // Copy of instrumentationClass.
    ComponentName mResultClass;

    // Contains all running processes that have active instrumentation.
    final ArrayList<ProcessRecord> mRunningProcesses = new ArrayList<>();

    // Set to true when we have told the watcher the instrumentation is finished.
    boolean mFinished;

    // The uid of the process who started this instrumentation.
    int mSourceUid;

    // True if instrumentation should take place without restarting the target process.
    boolean mNoRestart;

    ActiveInstrumentation(ActivityManagerService service) {
        mService = service;
    }

    void removeProcess(ProcessRecord proc) {
        mFinished = true;
        mRunningProcesses.remove(proc);
        if (mRunningProcesses.size() == 0) {
            mService.mActiveInstrumentation.remove(this);
        }
    }

    public String toString() {
        StringBuilder sb = new StringBuilder(128);
        sb.append("ActiveInstrumentation{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
        sb.append(' ');
        sb.append(mClass.toShortString());
        if (mFinished) {
            sb.append(" FINISHED");
        }
        sb.append(" ");
        sb.append(mRunningProcesses.size());
        sb.append(" procs");
        sb.append('}');
        return sb.toString();
    }

    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("mClass="); pw.print(mClass);
        pw.print(" mFinished="); pw.println(mFinished);
        pw.print(prefix); pw.println("mRunningProcesses:");
        for (int i=0; i<mRunningProcesses.size(); i++) {
            pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": ");
            pw.println(mRunningProcesses.get(i));
        }
        pw.print(prefix); pw.print("mTargetProcesses=");
        pw.println(Arrays.toString(mTargetProcesses));
        pw.print(prefix); pw.print("mTargetInfo=");
        pw.println(mTargetInfo);
        if (mTargetInfo != null) {
            mTargetInfo.dump(new PrintWriterPrinter(pw), prefix + "  ", 0);
        }
        if (mProfileFile != null) {
            pw.print(prefix); pw.print("mProfileFile="); pw.println(mProfileFile);
        }
        if (mWatcher != null) {
            pw.print(prefix); pw.print("mWatcher="); pw.println(mWatcher);
        }
        if (mUiAutomationConnection != null) {
            pw.print(prefix); pw.print("mUiAutomationConnection=");
            pw.println(mUiAutomationConnection);
        }
        pw.print("mHasBackgroundActivityStartsPermission=");
        pw.println(mHasBackgroundActivityStartsPermission);
        pw.print("mHasBackgroundForegroundServiceStartsPermission=");
        pw.println(mHasBackgroundForegroundServiceStartsPermission);
        pw.print(prefix); pw.print("mArguments=");
        pw.println(mArguments);
    }

    void dumpDebug(ProtoOutputStream proto, long fieldId) {
        long token = proto.start(fieldId);
        mClass.dumpDebug(proto, ActiveInstrumentationProto.CLASS);
        proto.write(ActiveInstrumentationProto.FINISHED, mFinished);
        for (int i=0; i<mRunningProcesses.size(); i++) {
            mRunningProcesses.get(i).dumpDebug(proto,
                    ActiveInstrumentationProto.RUNNING_PROCESSES);
        }
        for (String p : mTargetProcesses) {
            proto.write(ActiveInstrumentationProto.TARGET_PROCESSES, p);
        }
        if (mTargetInfo != null) {
            mTargetInfo.dumpDebug(proto, ActiveInstrumentationProto.TARGET_INFO, 0);
        }
        proto.write(ActiveInstrumentationProto.PROFILE_FILE, mProfileFile);
        proto.write(ActiveInstrumentationProto.WATCHER, mWatcher.toString());
        proto.write(ActiveInstrumentationProto.UI_AUTOMATION_CONNECTION,
                mUiAutomationConnection.toString());
        if (mArguments != null) {
            mArguments.dumpDebug(proto, ActiveInstrumentationProto.ARGUMENTS);
        }
        proto.end(token);
    }
}
