/*
 * 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;

    // Where to save profiling
    String mProfileFile;

    // Who is waiting
    IInstrumentationWatcher mWatcher;

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

    // 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;

    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(prefix); pw.print("mArguments=");
        pw.println(mArguments);
    }

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