OSDN Git Service

51102a624a0b9242f07578b3ae4728c23d6f9853
[android-x86/packages-apps-Settings.git] / src / com / android / settings / core / instrumentation / SharedPreferencesLogger.java
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14
15 package com.android.settings.core.instrumentation;
16
17 import android.annotation.Nullable;
18 import android.content.ComponentName;
19 import android.content.Context;
20 import android.content.SharedPreferences;
21 import android.content.pm.PackageManager;
22 import android.os.AsyncTask;
23 import android.text.TextUtils;
24 import android.util.Log;
25 import android.util.Pair;
26
27 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
28 import com.android.settings.overlay.FeatureFactory;
29
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.concurrent.ConcurrentSkipListSet;
33
34 public class SharedPreferencesLogger implements SharedPreferences {
35
36     private static final String LOG_TAG = "SharedPreferencesLogger";
37
38     private final String mTag;
39     private final Context mContext;
40     private final MetricsFeatureProvider mMetricsFeature;
41     private final Set<String> mPreferenceKeySet;
42
43     public SharedPreferencesLogger(Context context, String tag) {
44         mContext = context;
45         mTag = tag;
46         mMetricsFeature = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
47         mPreferenceKeySet = new ConcurrentSkipListSet<>();
48     }
49
50     @Override
51     public Map<String, ?> getAll() {
52         return null;
53     }
54
55     @Override
56     public String getString(String key, @Nullable String defValue) {
57         return defValue;
58     }
59
60     @Override
61     public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
62         return defValues;
63     }
64
65     @Override
66     public int getInt(String key, int defValue) {
67         return defValue;
68     }
69
70     @Override
71     public long getLong(String key, long defValue) {
72         return defValue;
73     }
74
75     @Override
76     public float getFloat(String key, float defValue) {
77         return defValue;
78     }
79
80     @Override
81     public boolean getBoolean(String key, boolean defValue) {
82         return defValue;
83     }
84
85     @Override
86     public boolean contains(String key) {
87         return false;
88     }
89
90     @Override
91     public Editor edit() {
92         return new EditorLogger();
93     }
94
95     @Override
96     public void registerOnSharedPreferenceChangeListener(
97             OnSharedPreferenceChangeListener listener) {
98     }
99
100     @Override
101     public void unregisterOnSharedPreferenceChangeListener(
102             OnSharedPreferenceChangeListener listener) {
103     }
104
105     private void logValue(String key, Object value) {
106         logValue(key, value, false /* forceLog */);
107     }
108
109     private void logValue(String key, Object value, boolean forceLog) {
110         final String prefKey = mTag + "/" + key;
111         if (!forceLog && !mPreferenceKeySet.contains(prefKey)) {
112             // Pref key doesn't exist in set, this is initial display so we skip metrics but
113             // keeps track of this key.
114             mPreferenceKeySet.add(prefKey);
115             return;
116         }
117         // TODO: Remove count logging to save some resource.
118         mMetricsFeature.count(mContext, prefKey + "|" + value, 1);
119
120         final Pair<Integer, Object> valueData;
121         if (value instanceof Long) {
122             valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
123                     value);
124         } else if (value instanceof Integer) {
125             valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
126                     ((Integer) value).longValue());
127         } else if (value instanceof Boolean) {
128             valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
129                     (Boolean) value ? 1L : 0L);
130         } else if (value instanceof Float) {
131             valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
132                     value);
133         } else if (value instanceof String){
134             valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_VALUE,
135                     value);
136         } else {
137             Log.w(LOG_TAG, "Tried to log unloggable object"  + value);
138             valueData = null;
139         }
140         if (valueData != null) {
141             // Pref key exists in set, log it's change in metrics.
142             mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
143                     Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
144                     valueData);
145         }
146     }
147
148     private void logPackageName(String key, String value) {
149         final String prefKey = mTag + "/" + key;
150         mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
151                 Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey));
152         mMetricsFeature.action(mContext, MetricsEvent.ACTION_GENERIC_PACKAGE,
153                 prefKey + "|" + value);
154     }
155
156     private void safeLogValue(String key, String value) {
157         new AsyncPackageCheck().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, key, value);
158     }
159
160     private class AsyncPackageCheck extends AsyncTask<String, Void, Void> {
161         @Override
162         protected Void doInBackground(String... params) {
163             String key = params[0];
164             String value = params[1];
165             PackageManager pm = mContext.getPackageManager();
166             try {
167                 // Check if this might be a component.
168                 ComponentName name = ComponentName.unflattenFromString(value);
169                 if (value != null) {
170                     value = name.getPackageName();
171                 }
172             } catch (Exception e) {
173             }
174             try {
175                 pm.getPackageInfo(value, PackageManager.MATCH_ANY_USER);
176                 logPackageName(key, value);
177             } catch (PackageManager.NameNotFoundException e) {
178                 // Clearly not a package, and it's unlikely this preference is in prefSet, so
179                 // lets force log it.
180                 logValue(key, value, true /* forceLog */);
181             }
182             return null;
183         }
184     }
185
186     public class EditorLogger implements Editor {
187         @Override
188         public Editor putString(String key, @Nullable String value) {
189             safeLogValue(key, value);
190             return this;
191         }
192
193         @Override
194         public Editor putStringSet(String key, @Nullable Set<String> values) {
195             safeLogValue(key, TextUtils.join(",", values));
196             return this;
197         }
198
199         @Override
200         public Editor putInt(String key, int value) {
201             logValue(key, value);
202             return this;
203         }
204
205         @Override
206         public Editor putLong(String key, long value) {
207             logValue(key, value);
208             return this;
209         }
210
211         @Override
212         public Editor putFloat(String key, float value) {
213             logValue(key, value);
214             return this;
215         }
216
217         @Override
218         public Editor putBoolean(String key, boolean value) {
219             logValue(key, value);
220             return this;
221         }
222
223         @Override
224         public Editor remove(String key) {
225             return this;
226         }
227
228         @Override
229         public Editor clear() {
230             return this;
231         }
232
233         @Override
234         public boolean commit() {
235             return true;
236         }
237
238         @Override
239         public void apply() {
240         }
241     }
242 }