1f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge/* 2f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * Copyright (C) 2013 The Android Open Source Project 3f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 4f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * Licensed under the Apache License, Version 2.0 (the "License"); 5f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * you may not use this file except in compliance with the License. 6f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * You may obtain a copy of the License at 7f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 8f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * http://www.apache.org/licenses/LICENSE-2.0 9f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 10f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * Unless required by applicable law or agreed to in writing, software 11f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * distributed under the License is distributed on an "AS IS" BASIS, 12f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * See the License for the specific language governing permissions and 14f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * limitations under the License. 15f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge */ 16f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 17f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridgepackage com.android.inputmethod.research; 18f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 19b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport android.content.SharedPreferences; 20b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport android.util.JsonWriter; 21b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport android.util.Log; 22b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport android.view.MotionEvent; 23b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport android.view.inputmethod.CompletionInfo; 24b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge 25b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport com.android.inputmethod.keyboard.Key; 26b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport com.android.inputmethod.latin.SuggestedWords; 27b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport com.android.inputmethod.latin.define.ProductionFlag; 28b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge 29b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridgeimport java.io.IOException; 30b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge 31f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge/** 32f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * A template for typed information stored in the logs. 33f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 34f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * A LogStatement contains a name, keys, and flags about whether the {@code Object[] values} 35f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * associated with the {@code String[] keys} are likely to reveal information about the user. The 36f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * actual values are stored separately. 37f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge */ 38531dd150eb1ddf88cb09c404a14834893c82f960Kurt Partridgepublic class LogStatement { 39b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge private static final String TAG = LogStatement.class.getSimpleName(); 409c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa private static final boolean DEBUG = false 419c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG; 42b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge 43f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // Constants for particular statements 44f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public static final String TYPE_POINTER_TRACKER_CALL_LISTENER_ON_CODE_INPUT = 45f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge "PointerTrackerCallListenerOnCodeInput"; 46f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public static final String KEY_CODE = "code"; 47f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public static final String VALUE_RESEARCH = "research"; 48c20a415e151404414c0195fdd8a64918452d8027Kurt Partridge public static final String TYPE_MAIN_KEYBOARD_VIEW_ON_LONG_PRESS = 49c20a415e151404414c0195fdd8a64918452d8027Kurt Partridge "MainKeyboardViewOnLongPress"; 50f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public static final String ACTION = "action"; 51f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public static final String VALUE_DOWN = "DOWN"; 52c20a415e151404414c0195fdd8a64918452d8027Kurt Partridge public static final String TYPE_MOTION_EVENT = "MotionEvent"; 53c20a415e151404414c0195fdd8a64918452d8027Kurt Partridge public static final String KEY_IS_LOGGING_RELATED = "isLoggingRelated"; 54f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 55b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge // Keys for internal key/value pairs 56b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge private static final String CURRENT_TIME_KEY = "_ct"; 57b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge private static final String UPTIME_KEY = "_ut"; 58b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge private static final String EVENT_TYPE_KEY = "_ty"; 59b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge 60f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // Name specifying the LogStatement type. 61f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge private final String mType; 62f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 63f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // mIsPotentiallyPrivate indicates that event contains potentially private information. If 64f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // the word that this event is a part of is determined to be privacy-sensitive, then this 65f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // event should not be included in the output log. The system waits to output until the 66f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // containing word is known. 67f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge private final boolean mIsPotentiallyPrivate; 68f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 69f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // mIsPotentiallyRevealing indicates that this statement may disclose details about other 70f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // words typed in other LogUnits. This can happen if the user is not inserting spaces, and 71f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // data from Suggestions and/or Composing text reveals the entire "megaword". For example, 72f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // say the user is typing "for the win", and the system wants to record the bigram "the 73f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // win". If the user types "forthe", omitting the space, the system will give "for the" as 74f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // a suggestion. If the user accepts the autocorrection, the suggestion for "for the" is 75f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // included in the log for the word "the", disclosing that the previous word had been "for". 76f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // For now, we simply do not include this data when logging part of a "megaword". 77f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge private final boolean mIsPotentiallyRevealing; 78f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 79f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge // mKeys stores the names that are the attributes in the output json objects 80f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge private final String[] mKeys; 81f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge private static final String[] NULL_KEYS = new String[0]; 82f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 83f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge LogStatement(final String name, final boolean isPotentiallyPrivate, 84f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge final boolean isPotentiallyRevealing, final String... keys) { 85f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge mType = name; 86f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge mIsPotentiallyPrivate = isPotentiallyPrivate; 87f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge mIsPotentiallyRevealing = isPotentiallyRevealing; 88f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge mKeys = (keys == null) ? NULL_KEYS : keys; 89f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 90f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 91f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public String getType() { 92f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge return mType; 93f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 94f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 95f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public boolean isPotentiallyPrivate() { 96f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge return mIsPotentiallyPrivate; 97f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 98f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 99f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public boolean isPotentiallyRevealing() { 100f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge return mIsPotentiallyRevealing; 101f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 102f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 103f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public String[] getKeys() { 104f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge return mKeys; 105f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 106f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 107f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge /** 108f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * Utility function to test whether a key-value pair exists in a LogStatement. 109f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 110f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * A LogStatement is really just a template -- it does not contain the values, only the 111f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * keys. So the values must be passed in as an argument. 112f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 113f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @param queryKey the String that is tested by {@code String.equals()} to the keys in the 114f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * LogStatement 115f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @param queryValue an Object that must be {@code Object.equals()} to the key's corresponding 116f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * value in the {@code values} array 117f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @param values the values corresponding to mKeys 118f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 119f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @returns {@true} if {@code queryKey} exists in the keys for this LogStatement, and {@code 120f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * queryValue} matches the corresponding value in {@code values} 121f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 122f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @throws IllegalArgumentException if {@code values.length} is not equal to keys().length() 123f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge */ 124f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public boolean containsKeyValuePair(final String queryKey, final Object queryValue, 125f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge final Object[] values) { 126f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge if (mKeys.length != values.length) { 127f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge throw new IllegalArgumentException("Mismatched number of keys and values."); 128f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 129f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge final int length = mKeys.length; 130f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge for (int i = 0; i < length; i++) { 131f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge if (mKeys[i].equals(queryKey) && values[i].equals(queryValue)) { 132f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge return true; 133f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 134f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 135f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge return false; 136f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 137f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge 138f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge /** 139f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * Utility function to set a value in a LogStatement. 140f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 141f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * A LogStatement is really just a template -- it does not contain the values, only the 142f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * keys. So the values must be passed in as an argument. 143f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 144f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @param queryKey the String that is tested by {@code String.equals()} to the keys in the 145f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * LogStatement 146f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @param values the array of values corresponding to mKeys 147f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @param newValue the replacement value to go into the {@code values} array 148f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 149f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @returns {@true} if the key exists and the value was successfully set, {@false} otherwise 150f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * 151f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge * @throws IllegalArgumentException if {@code values.length} is not equal to keys().length() 152f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge */ 153f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge public boolean setValue(final String queryKey, final Object[] values, final Object newValue) { 154f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge if (mKeys.length != values.length) { 155f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge throw new IllegalArgumentException("Mismatched number of keys and values."); 156f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 157f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge final int length = mKeys.length; 158f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge for (int i = 0; i < length; i++) { 159f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge if (mKeys[i].equals(queryKey)) { 160f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge values[i] = newValue; 161f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge return true; 162f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 163f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 164f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge return false; 165f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge } 166b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge 167b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge /** 168b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge * Write the contents out through jsonWriter. 169b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge * 170531dd150eb1ddf88cb09c404a14834893c82f960Kurt Partridge * The JsonWriter class must have already had {@code JsonWriter.beginArray} called on it. 171531dd150eb1ddf88cb09c404a14834893c82f960Kurt Partridge * 172b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge * Note that this method is not thread safe for the same jsonWriter. Callers must ensure 173b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge * thread safety. 174b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge */ 175b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge public boolean outputToLocked(final JsonWriter jsonWriter, final Long time, 176b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge final Object... values) { 177b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge if (DEBUG) { 178b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge if (mKeys.length != values.length) { 179b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge Log.d(TAG, "Key and Value list sizes do not match. " + mType); 180b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } 181b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } 182b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge try { 183b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.beginObject(); 184b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis()); 185b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.name(UPTIME_KEY).value(time); 186b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.name(EVENT_TYPE_KEY).value(mType); 187b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge final int length = values.length; 188b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge for (int i = 0; i < length; i++) { 189b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.name(mKeys[i]); 190b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge final Object value = values[i]; 191b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge if (value instanceof CharSequence) { 192b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.value(value.toString()); 193b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else if (value instanceof Number) { 194b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.value((Number) value); 195b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else if (value instanceof Boolean) { 196b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.value((Boolean) value); 197b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else if (value instanceof CompletionInfo[]) { 198b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge JsonUtils.writeJson((CompletionInfo[]) value, jsonWriter); 199b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else if (value instanceof SharedPreferences) { 200b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge JsonUtils.writeJson((SharedPreferences) value, jsonWriter); 201b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else if (value instanceof Key[]) { 202b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge JsonUtils.writeJson((Key[]) value, jsonWriter); 203b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else if (value instanceof SuggestedWords) { 204b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge JsonUtils.writeJson((SuggestedWords) value, jsonWriter); 205b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else if (value instanceof MotionEvent) { 206b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge JsonUtils.writeJson((MotionEvent) value, jsonWriter); 207b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else if (value == null) { 208b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.nullValue(); 209b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } else { 210b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge if (DEBUG) { 211b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge Log.w(TAG, "Unrecognized type to be logged: " 212b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge + (value == null ? "<null>" : value.getClass().getName())); 213b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } 214b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.nullValue(); 215b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } 216b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } 217b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge jsonWriter.endObject(); 218b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } catch (IOException e) { 219b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge e.printStackTrace(); 220b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge Log.w(TAG, "Error in JsonWriter; skipping LogStatement"); 221b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge return false; 222b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } 223b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge return true; 224b02a19c49d29cd7758d01349ebbfeb479a56bb37Kurt Partridge } 225f3731188e5ee46c0bee7e9366528c826289a91bbKurt Partridge} 226