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 public boolean tokenProvided; 60 61 /** Callback for key eviction. */ 62 public interface KeyEvictedCallback { 63 /** Invoked when the key is evicted. */ keyEvicted(@serIdInt int userId)64 void keyEvicted(@UserIdInt int userId); 65 } 66 67 /** 68 * The last time that a provider was reported to usage stats as being brought to important 69 * foreground procstate. 70 * <p><strong>Important: </strong>Only access this field when holding ActivityManagerService 71 * lock. 72 */ 73 final ArrayMap<String,Long> mProviderLastReportedFg = new ArrayMap<>(); 74 UserState(UserHandle handle)75 public UserState(UserHandle handle) { 76 mHandle = handle; 77 mUnlockProgress = new ProgressReporter(handle.getIdentifier()); 78 } 79 setState(int oldState, int newState)80 public boolean setState(int oldState, int newState) { 81 if (state == oldState) { 82 setState(newState); 83 return true; 84 } else { 85 Slog.w(TAG, "Expected user " + mHandle.getIdentifier() + " in state " 86 + stateToString(oldState) + " but was in state " + stateToString(state)); 87 return false; 88 } 89 } 90 setState(int newState)91 public void setState(int newState) { 92 if (newState == state) { 93 return; 94 } 95 final int userId = mHandle.getIdentifier(); 96 if (state != STATE_BOOTING) { 97 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, 98 stateToString(state) + " " + userId, userId); 99 } 100 if (newState != STATE_SHUTDOWN) { 101 Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 102 stateToString(newState) + " " + userId, userId); 103 } 104 Slog.i(TAG, "User " + userId + " state changed from " 105 + stateToString(state) + " to " + stateToString(newState)); 106 EventLogTags.writeAmUserStateChanged(userId, newState); 107 lastState = state; 108 state = newState; 109 } 110 stateToString(int state)111 public static String stateToString(int state) { 112 switch (state) { 113 case STATE_BOOTING: return "BOOTING"; 114 case STATE_RUNNING_LOCKED: return "RUNNING_LOCKED"; 115 case STATE_RUNNING_UNLOCKING: return "RUNNING_UNLOCKING"; 116 case STATE_RUNNING_UNLOCKED: return "RUNNING_UNLOCKED"; 117 case STATE_STOPPING: return "STOPPING"; 118 case STATE_SHUTDOWN: return "SHUTDOWN"; 119 default: return Integer.toString(state); 120 } 121 } 122 stateToProtoEnum(int state)123 public static int stateToProtoEnum(int state) { 124 switch (state) { 125 case STATE_BOOTING: return UserStateProto.STATE_BOOTING; 126 case STATE_RUNNING_LOCKED: return UserStateProto.STATE_RUNNING_LOCKED; 127 case STATE_RUNNING_UNLOCKING: return UserStateProto.STATE_RUNNING_UNLOCKING; 128 case STATE_RUNNING_UNLOCKED: return UserStateProto.STATE_RUNNING_UNLOCKED; 129 case STATE_STOPPING: return UserStateProto.STATE_STOPPING; 130 case STATE_SHUTDOWN: return UserStateProto.STATE_SHUTDOWN; 131 default: return state; 132 } 133 } 134 dump(String prefix, PrintWriter pw)135 void dump(String prefix, PrintWriter pw) { 136 pw.print(prefix); 137 pw.print("state="); pw.print(stateToString(state)); 138 if (switching) pw.print(" SWITCHING"); 139 pw.println(); 140 } 141 dumpDebug(ProtoOutputStream proto, long fieldId)142 void dumpDebug(ProtoOutputStream proto, long fieldId) { 143 final long token = proto.start(fieldId); 144 proto.write(UserStateProto.STATE, stateToProtoEnum(state)); 145 proto.write(UserStateProto.SWITCHING, switching); 146 proto.end(token); 147 } 148 } 149