/*
 * Copyright (C) 2012 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 com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;

import android.annotation.UserIdInt;
import android.app.IStopUserCallback;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;

import com.android.internal.util.ProgressReporter;

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

public final class UserState {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "UserState" : TAG_AM;

    // user doesn't exist.
    public static final int STATE_NONE = -1;
    // User is first coming up.
    public static final int STATE_BOOTING = 0;
    // User is in the locked state.
    public static final int STATE_RUNNING_LOCKED = 1;
    // User is in the unlocking state.
    public static final int STATE_RUNNING_UNLOCKING = 2;
    // User is in the running state.
    public static final int STATE_RUNNING_UNLOCKED = 3;
    // User is in the initial process of being stopped.
    public static final int STATE_STOPPING = 4;
    // User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN.
    public static final int STATE_SHUTDOWN = 5;

    public final UserHandle mHandle;
    public final ArrayList<IStopUserCallback> mStopCallbacks = new ArrayList<>();
    public final ProgressReporter mUnlockProgress;
    public final ArrayList<KeyEvictedCallback> mKeyEvictedCallbacks = new ArrayList<>();

    public int state = STATE_BOOTING;
    public int lastState = STATE_BOOTING;
    public boolean switching;

    /** Callback for key eviction. */
    public interface KeyEvictedCallback {
        /** Invoked when the key is evicted. */
        void keyEvicted(@UserIdInt int userId);
    }

    /**
     * The last time that a provider was reported to usage stats as being brought to important
     * foreground procstate.
     * <p><strong>Important: </strong>Only access this field when holding ActivityManagerService
     * lock.
     */
    final ArrayMap<String,Long> mProviderLastReportedFg = new ArrayMap<>();

    public UserState(UserHandle handle) {
        mHandle = handle;
        mUnlockProgress = new ProgressReporter(handle.getIdentifier());
    }

    public boolean setState(int oldState, int newState) {
        if (state == oldState) {
            setState(newState);
            return true;
        } else {
            Slog.w(TAG, "Expected user " + mHandle.getIdentifier() + " in state "
                    + stateToString(oldState) + " but was in state " + stateToString(state));
            return false;
        }
    }

    public void setState(int newState) {
        if (newState == state) {
            return;
        }
        final int userId = mHandle.getIdentifier();
        if (state != STATE_BOOTING) {
            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    stateToString(state) + " " + userId, userId);
        }
        if (newState != STATE_SHUTDOWN) {
            Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    stateToString(newState) + " " + userId, userId);
        }
        Slog.i(TAG, "User " + userId + " state changed from "
                + stateToString(state) + " to " + stateToString(newState));
        EventLogTags.writeAmUserStateChanged(userId, newState);
        lastState = state;
        state = newState;
    }

    public static String stateToString(int state) {
        switch (state) {
            case STATE_BOOTING: return "BOOTING";
            case STATE_RUNNING_LOCKED: return "RUNNING_LOCKED";
            case STATE_RUNNING_UNLOCKING: return "RUNNING_UNLOCKING";
            case STATE_RUNNING_UNLOCKED: return "RUNNING_UNLOCKED";
            case STATE_STOPPING: return "STOPPING";
            case STATE_SHUTDOWN: return "SHUTDOWN";
            default: return Integer.toString(state);
        }
    }

    public static int stateToProtoEnum(int state) {
        switch (state) {
            case STATE_BOOTING: return UserStateProto.STATE_BOOTING;
            case STATE_RUNNING_LOCKED: return UserStateProto.STATE_RUNNING_LOCKED;
            case STATE_RUNNING_UNLOCKING: return UserStateProto.STATE_RUNNING_UNLOCKING;
            case STATE_RUNNING_UNLOCKED: return UserStateProto.STATE_RUNNING_UNLOCKED;
            case STATE_STOPPING: return UserStateProto.STATE_STOPPING;
            case STATE_SHUTDOWN: return UserStateProto.STATE_SHUTDOWN;
            default: return state;
        }
    }

    void dump(String prefix, PrintWriter pw) {
        pw.print(prefix);
        pw.print("state="); pw.print(stateToString(state));
        if (switching) pw.print(" SWITCHING");
        pw.println();
    }

    void dumpDebug(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        proto.write(UserStateProto.STATE, stateToProtoEnum(state));
        proto.write(UserStateProto.SWITCHING, switching);
        proto.end(token);
    }

    @Override
    public String toString() {
        return "[UserState: id=" + mHandle.getIdentifier() + ", state=" + stateToString(state)
            + ", lastState=" + stateToString(lastState) + ", switching=" + switching + "]";
    }
}
