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 doesn't exist. 39 public static final int STATE_NONE = -1; 40 // User is first coming up. 41 public static final int STATE_BOOTING = 0; 42 // User is in the locked state. 43 public static final int STATE_RUNNING_LOCKED = 1; 44 // User is in the unlocking state. 45 public static final int STATE_RUNNING_UNLOCKING = 2; 46 // User is in the running state. 47 public static final int STATE_RUNNING_UNLOCKED = 3; 48 // User is in the initial process of being stopped. 49 public static final int STATE_STOPPING = 4; 50 // User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN. 51 public static final int STATE_SHUTDOWN = 5; 52 53 public final UserHandle mHandle; 54 public final ArrayList<IStopUserCallback> mStopCallbacks = new ArrayList<>(); 55 public final ProgressReporter mUnlockProgress; 56 public final ArrayList<KeyEvictedCallback> mKeyEvictedCallbacks = new ArrayList<>(); 57 58 public int state = STATE_BOOTING; 59 public int lastState = STATE_BOOTING; 60 public boolean switching; 61 62 /** Callback for key eviction. */ 63 public interface KeyEvictedCallback { 64 /** Invoked when the key is evicted. */ keyEvicted(@serIdInt int userId)65 void keyEvicted(@UserIdInt int userId); 66 } 67 68 /** 69 * The last time that a provider was reported to usage stats as being brought to important 70 * foreground procstate. 71 * <p><strong>Important: </strong>Only access this field when holding ActivityManagerService 72 * lock. 73 */ 74 final ArrayMap<String,Long> mProviderLastReportedFg = new ArrayMap<>(); 75 UserState(UserHandle handle)76 public UserState(UserHandle handle) { 77 mHandle = handle; 78 mUnlockProgress = new ProgressReporter(handle.getIdentifier()); 79 } 80 setState(int oldState, int newState)81 public boolean setState(int oldState, int newState) { 82 if (state == oldState) { 83 setState(newState); 84 return true; 85 } else { 86 Slog.w(TAG, "Expected user " + mHandle.getIdentifier() + " in state " 87 + stateToString(oldState) + " but was in state " + stateToString(state)); 88 return false; 89 } 90 } 91 setState(int newState)92 public void setState(int newState) { 93 if (newState == state) { 94 return; 95 } 96 final int userId = mHandle.getIdentifier(); 97 if (state != STATE_BOOTING) { 98 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, 99 stateToString(state) + " " + userId, userId); 100 } 101 if (newState != STATE_SHUTDOWN) { 102 Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 103 stateToString(newState) + " " + userId, userId); 104 } 105 Slog.i(TAG, "User " + userId + " state changed from " 106 + stateToString(state) + " to " + stateToString(newState)); 107 EventLogTags.writeAmUserStateChanged(userId, newState); 108 lastState = state; 109 state = newState; 110 } 111 stateToString(int state)112 public static String stateToString(int state) { 113 switch (state) { 114 case STATE_BOOTING: return "BOOTING"; 115 case STATE_RUNNING_LOCKED: return "RUNNING_LOCKED"; 116 case STATE_RUNNING_UNLOCKING: return "RUNNING_UNLOCKING"; 117 case STATE_RUNNING_UNLOCKED: return "RUNNING_UNLOCKED"; 118 case STATE_STOPPING: return "STOPPING"; 119 case STATE_SHUTDOWN: return "SHUTDOWN"; 120 default: return Integer.toString(state); 121 } 122 } 123 stateToProtoEnum(int state)124 public static int stateToProtoEnum(int state) { 125 switch (state) { 126 case STATE_BOOTING: return UserStateProto.STATE_BOOTING; 127 case STATE_RUNNING_LOCKED: return UserStateProto.STATE_RUNNING_LOCKED; 128 case STATE_RUNNING_UNLOCKING: return UserStateProto.STATE_RUNNING_UNLOCKING; 129 case STATE_RUNNING_UNLOCKED: return UserStateProto.STATE_RUNNING_UNLOCKED; 130 case STATE_STOPPING: return UserStateProto.STATE_STOPPING; 131 case STATE_SHUTDOWN: return UserStateProto.STATE_SHUTDOWN; 132 default: return state; 133 } 134 } 135 dump(String prefix, PrintWriter pw)136 void dump(String prefix, PrintWriter pw) { 137 pw.print(prefix); 138 pw.print("state="); pw.print(stateToString(state)); 139 if (switching) pw.print(" SWITCHING"); 140 pw.println(); 141 } 142 dumpDebug(ProtoOutputStream proto, long fieldId)143 void dumpDebug(ProtoOutputStream proto, long fieldId) { 144 final long token = proto.start(fieldId); 145 proto.write(UserStateProto.STATE, stateToProtoEnum(state)); 146 proto.write(UserStateProto.SWITCHING, switching); 147 proto.end(token); 148 } 149 150 @Override toString()151 public String toString() { 152 return "[UserState: id=" + mHandle.getIdentifier() + ", state=" + stateToString(state) 153 + ", lastState=" + stateToString(lastState) + ", switching=" + switching + "]"; 154 } 155 } 156