1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package android.testing;
import android.content.ContentProviderClient;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.test.mock.MockContentProvider;
import android.util.Log;
import java.util.HashMap;
import static org.junit.Assert.*;
/**
* Allows calls to android.provider.Settings to be tested easier.
*
* This provides a simple copy-on-write implementation of settings that gets cleared
* at the end of each test.
*/
public class TestableSettingsProvider extends MockContentProvider {
private static final String TAG = "TestableSettingsProvider";
private static final boolean DEBUG = false;
private static final String MY_UNIQUE_KEY = "Key_" + TestableSettingsProvider.class.getName();
private static TestableSettingsProvider sInstance;
private final ContentProviderClient mSettings;
private final HashMap<String, String> mValues = new HashMap<>();
private TestableSettingsProvider(ContentProviderClient settings) {
mSettings = settings;
}
void clearValuesAndCheck(Context context) {
int userId = UserHandle.myUserId();
mValues.put(key("global", MY_UNIQUE_KEY, userId), MY_UNIQUE_KEY);
mValues.put(key("secure", MY_UNIQUE_KEY, userId), MY_UNIQUE_KEY);
mValues.put(key("system", MY_UNIQUE_KEY, userId), MY_UNIQUE_KEY);
// Verify that if any test is using TestableContext, they all have the correct settings
// provider.
assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY,
Settings.Global.getString(context.getContentResolver(), MY_UNIQUE_KEY));
assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY,
Settings.Secure.getString(context.getContentResolver(), MY_UNIQUE_KEY));
assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY,
Settings.System.getString(context.getContentResolver(), MY_UNIQUE_KEY));
mValues.clear();
}
public Bundle call(String method, String arg, Bundle extras) {
// Methods are "GET_system", "GET_global", "PUT_secure", etc.
final int userId = extras.getInt(Settings.CALL_METHOD_USER_KEY, 0);
final String[] commands = method.split("_", 2);
final String op = commands[0];
final String table = commands[1];
String k = key(table, arg, userId);
String value;
Bundle out = new Bundle();
switch (op) {
case "GET":
if (mValues.containsKey(k)) {
value = mValues.get(k);
if (value != null) {
out.putString(Settings.NameValueTable.VALUE, value);
}
} else {
// Fall through to real settings.
try {
if (DEBUG) Log.d(TAG, "Falling through to real settings " + method);
// TODO: Add our own version of caching to handle this.
Bundle call = mSettings.call(method, arg, extras);
call.remove(Settings.CALL_METHOD_TRACK_GENERATION_KEY);
return call;
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
break;
case "PUT":
value = extras.getString(Settings.NameValueTable.VALUE, null);
mValues.put(k, value);
break;
default:
throw new UnsupportedOperationException("Unknown command " + method);
}
return out;
}
private static String key(String table, String key, int userId) {
if ("global".equals(table)) {
return table + "_" + key;
} else {
return table + "_" + userId + "_" + key;
}
}
/**
* Since the settings provider is cached inside android.provider.Settings, this must
* be gotten statically to ensure there is only one instance referenced.
*/
static TestableSettingsProvider getFakeSettingsProvider(ContentProviderClient settings) {
if (sInstance == null) {
sInstance = new TestableSettingsProvider(settings);
}
return sInstance;
}
}
|