1 /* 2 * Copyright (C) 2024 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.inputmethod; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.os.SystemClock; 22 import android.view.WindowManager; 23 import android.view.inputmethod.EditorInfo; 24 25 import com.android.internal.inputmethod.InputMethodDebug; 26 import com.android.internal.inputmethod.SoftInputShowHideReason; 27 28 import java.io.PrintWriter; 29 import java.time.Instant; 30 import java.time.ZoneId; 31 import java.time.format.DateTimeFormatter; 32 import java.util.Locale; 33 import java.util.concurrent.atomic.AtomicInteger; 34 35 final class SoftInputShowHideHistory { 36 private static final AtomicInteger sSequenceNumber = new AtomicInteger(0); 37 38 private final Entry[] mEntries = new Entry[16]; 39 private int mNextIndex = 0; 40 41 static final class Entry { 42 final int mSequenceNumber = sSequenceNumber.getAndIncrement(); 43 @Nullable 44 final ClientState mClientState; 45 @WindowManager.LayoutParams.SoftInputModeFlags 46 final int mFocusedWindowSoftInputMode; 47 @SoftInputShowHideReason 48 final int mReason; 49 // The timing of handling showCurrentInputLocked() or hideCurrentInputLocked(). 50 final long mTimestamp; 51 final long mWallTime; 52 final boolean mInFullscreenMode; 53 @NonNull 54 final String mFocusedWindowName; 55 @Nullable 56 final EditorInfo mEditorInfo; 57 @NonNull 58 final String mRequestWindowName; 59 @Nullable 60 final String mImeControlTargetName; 61 @Nullable 62 final String mImeTargetNameFromWm; 63 @Nullable 64 final String mImeSurfaceParentName; 65 Entry(ClientState client, EditorInfo editorInfo, String focusedWindowName, @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode, @SoftInputShowHideReason int reason, boolean inFullscreenMode, String requestWindowName, @Nullable String imeControlTargetName, @Nullable String imeTargetName, @Nullable String imeSurfaceParentName)66 Entry(ClientState client, EditorInfo editorInfo, 67 String focusedWindowName, 68 @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode, 69 @SoftInputShowHideReason int reason, 70 boolean inFullscreenMode, String requestWindowName, 71 @Nullable String imeControlTargetName, @Nullable String imeTargetName, 72 @Nullable String imeSurfaceParentName) { 73 mClientState = client; 74 mEditorInfo = editorInfo; 75 mFocusedWindowName = focusedWindowName; 76 mFocusedWindowSoftInputMode = softInputMode; 77 mReason = reason; 78 mTimestamp = SystemClock.uptimeMillis(); 79 mWallTime = System.currentTimeMillis(); 80 mInFullscreenMode = inFullscreenMode; 81 mRequestWindowName = requestWindowName; 82 mImeControlTargetName = imeControlTargetName; 83 mImeTargetNameFromWm = imeTargetName; 84 mImeSurfaceParentName = imeSurfaceParentName; 85 } 86 } 87 addEntry(@onNull Entry entry)88 void addEntry(@NonNull Entry entry) { 89 final int index = mNextIndex; 90 mEntries[index] = entry; 91 mNextIndex = (mNextIndex + 1) % mEntries.length; 92 } 93 dump(@onNull PrintWriter pw, @NonNull String prefix)94 void dump(@NonNull PrintWriter pw, @NonNull String prefix) { 95 final DateTimeFormatter formatter = 96 DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS", Locale.US) 97 .withZone(ZoneId.systemDefault()); 98 99 for (int i = 0; i < mEntries.length; ++i) { 100 final Entry entry = mEntries[(i + mNextIndex) % mEntries.length]; 101 if (entry == null) { 102 continue; 103 } 104 pw.print(prefix); 105 pw.println("SoftInputShowHide #" + entry.mSequenceNumber + ":"); 106 107 pw.print(prefix); 108 pw.println(" time=" + formatter.format(Instant.ofEpochMilli(entry.mWallTime)) 109 + " (timestamp=" + entry.mTimestamp + ")"); 110 111 pw.print(prefix); 112 pw.print(" reason=" + InputMethodDebug.softInputDisplayReasonToString( 113 entry.mReason)); 114 pw.println(" inFullscreenMode=" + entry.mInFullscreenMode); 115 116 pw.print(prefix); 117 pw.println(" requestClient=" + entry.mClientState); 118 119 pw.print(prefix); 120 pw.println(" focusedWindowName=" + entry.mFocusedWindowName); 121 122 pw.print(prefix); 123 pw.println(" requestWindowName=" + entry.mRequestWindowName); 124 125 pw.print(prefix); 126 pw.println(" imeControlTargetName=" + entry.mImeControlTargetName); 127 128 pw.print(prefix); 129 pw.println(" imeTargetNameFromWm=" + entry.mImeTargetNameFromWm); 130 131 pw.print(prefix); 132 pw.println(" imeSurfaceParentName=" + entry.mImeSurfaceParentName); 133 134 pw.print(prefix); 135 pw.print(" editorInfo:"); 136 if (entry.mEditorInfo != null) { 137 pw.print(" inputType=" + entry.mEditorInfo.inputType); 138 pw.print(" privateImeOptions=" + entry.mEditorInfo.privateImeOptions); 139 pw.println(" fieldId (viewId)=" + entry.mEditorInfo.fieldId); 140 } else { 141 pw.println(" null"); 142 } 143 144 pw.print(prefix); 145 pw.println(" focusedWindowSoftInputMode=" + InputMethodDebug.softInputModeToString( 146 entry.mFocusedWindowSoftInputMode)); 147 } 148 } 149 } 150