1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.am; 18 19 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 20 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 21 22 import android.annotation.UserIdInt; 23 import android.app.IStopUserCallback; 24 import android.os.Trace; 25 import android.os.UserHandle; 26 import android.util.ArrayMap; 27 import android.util.Slog; 28 import android.util.proto.ProtoOutputStream; 29 30 import com.android.internal.util.ProgressReporter; 31 32 import java.io.PrintWriter; 33 import java.util.ArrayList; 34 35 public final class UserState { 36 private static final String TAG = TAG_WITH_CLASS_NAME ? "UserState" : TAG_AM; 37 38 // User is first coming up. 39 public final static int STATE_BOOTING = 0; 40 // User is in the locked state. 41 public final static int STATE_RUNNING_LOCKED = 1; 42 // User is in the unlocking state. 43 public final static int STATE_RUNNING_UNLOCKING = 2; 44 // User is in the running state. 45 public final static int STATE_RUNNING_UNLOCKED = 3; 46 // User is in the initial process of being stopped. 47 public final static int STATE_STOPPING = 4; 48 // User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN. 49 public final static int STATE_SHUTDOWN = 5; 50 51 public final UserHandle mHandle; 52 public final ArrayList<IStopUserCallback> mStopCallbacks = new ArrayList<>(); 53 public final ProgressReporter mUnlockProgress; 54 public final ArrayList<KeyEvictedCallback> mKeyEvictedCallbacks = new ArrayList<>(); 55 56 public int state = STATE_BOOTING; 57 public int lastState = STATE_BOOTING; 58 public boolean switching; 59 60 /** Callback for key eviction. */ 61 public interface KeyEvictedCallback { 62 /** Invoked when the key is evicted. */ keyEvicted(@serIdInt int userId)63 void keyEvicted(@UserIdInt int userId); 64 } 65 66 /** 67 * The last time that a provider was reported to usage stats as being brought to important 68 * foreground procstate. 69 * <p><strong>Important: </strong>Only access this field when holding ActivityManagerService 70 * lock. 71 */ 72 final ArrayMap<String,Long> mProviderLastReportedFg = new ArrayMap<>(); 73 UserState(UserHandle handle)74 public UserState(UserHandle handle) { 75 mHandle = handle; 76 mUnlockProgress = new ProgressReporter(handle.getIdentifier()); 77 } 78 setState(int oldState, int newState)79 public boolean setState(int oldState, int newState) { 80 if (state == oldState) { 81 setState(newState); 82 return true; 83 } else { 84 Slog.w(TAG, "Expected user " + mHandle.getIdentifier() + " in state " 85 + stateToString(oldState) + " but was in state " + stateToString(state)); 86 return false; 87 } 88 } 89 setState(int newState)90 public void setState(int newState) { 91 if (newState == state) { 92 return; 93 } 94 final int userId = mHandle.getIdentifier(); 95 if (state != STATE_BOOTING) { 96 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, 97 stateToString(state) + " " + userId, userId); 98 } 99 if (newState != STATE_SHUTDOWN) { 100 Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 101 stateToString(newState) + " " + userId, userId); 102 } 103 Slog.i(TAG, "User " + userId + " state changed from " 104 + stateToString(state) + " to " + stateToString(newState)); 105 EventLogTags.writeAmUserStateChanged(userId, newState); 106 lastState = state; 107 state = newState; 108 } 109 stateToString(int state)110 public static String stateToString(int state) { 111 switch (state) { 112 case STATE_BOOTING: return "BOOTING"; 113 case STATE_RUNNING_LOCKED: return "RUNNING_LOCKED"; 114 case STATE_RUNNING_UNLOCKING: return "RUNNING_UNLOCKING"; 115 case STATE_RUNNING_UNLOCKED: return "RUNNING_UNLOCKED"; 116 case STATE_STOPPING: return "STOPPING"; 117 case STATE_SHUTDOWN: return "SHUTDOWN"; 118 default: return Integer.toString(state); 119 } 120 } 121 stateToProtoEnum(int state)122 public static int stateToProtoEnum(int state) { 123 switch (state) { 124 case STATE_BOOTING: return UserStateProto.STATE_BOOTING; 125 case STATE_RUNNING_LOCKED: return UserStateProto.STATE_RUNNING_LOCKED; 126 case STATE_RUNNING_UNLOCKING: return UserStateProto.STATE_RUNNING_UNLOCKING; 127 case STATE_RUNNING_UNLOCKED: return UserStateProto.STATE_RUNNING_UNLOCKED; 128 case STATE_STOPPING: return UserStateProto.STATE_STOPPING; 129 case STATE_SHUTDOWN: return UserStateProto.STATE_SHUTDOWN; 130 default: return state; 131 } 132 } 133 dump(String prefix, PrintWriter pw)134 void dump(String prefix, PrintWriter pw) { 135 pw.print(prefix); 136 pw.print("state="); pw.print(stateToString(state)); 137 if (switching) pw.print(" SWITCHING"); 138 pw.println(); 139 } 140 dumpDebug(ProtoOutputStream proto, long fieldId)141 void dumpDebug(ProtoOutputStream proto, long fieldId) { 142 final long token = proto.start(fieldId); 143 proto.write(UserStateProto.STATE, stateToProtoEnum(state)); 144 proto.write(UserStateProto.SWITCHING, switching); 145 proto.end(token); 146 } 147 148 @Override toString()149 public String toString() { 150 return "[UserState: id=" + mHandle.getIdentifier() + ", state=" + stateToString(state) 151 + ", lastState=" + stateToString(lastState) + ", switching=" + switching + "]"; 152 } 153 } 154