1683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav/*
2683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * Copyright (C) 2015 The Android Open Source Project
3683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav *
4683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * Licensed under the Apache License, Version 2.0 (the "License");
5683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * you may not use this file except in compliance with the License.
6683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * You may obtain a copy of the License at
7683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav *
8683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav *      http://www.apache.org/licenses/LICENSE-2.0
9683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav *
10683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * Unless required by applicable law or agreed to in writing, software
11683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * distributed under the License is distributed on an "AS IS" BASIS,
12683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * See the License for the specific language governing permissions and
14683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * limitations under the License.
15683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav */
16683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
17683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavpackage com.android.providers.settings;
18683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
19683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.content.ContentResolver;
20683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.content.ContentValues;
21683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.content.Context;
22683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.content.pm.UserInfo;
23683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.database.Cursor;
24683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.net.Uri;
25683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.os.UserHandle;
26683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.os.UserManager;
27683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport android.provider.Settings;
28e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganovimport android.support.test.InstrumentationRegistry;
29e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganovimport android.support.test.runner.AndroidJUnit4;
30e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganovimport libcore.io.Streams;
31e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganovimport org.junit.runner.RunWith;
32e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
33e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganovimport java.io.FileInputStream;
34e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganovimport java.io.IOException;
35e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganovimport java.io.InputStream;
36683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslavimport java.util.List;
37683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
38683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav/**
39683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav * Base class for the SettingContentProvider tests.
40683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav */
41e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov@RunWith(AndroidJUnit4.class)
42e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganovabstract class BaseSettingsProviderTest {
43683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected static final int SETTING_TYPE_GLOBAL = 1;
44683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected static final int SETTING_TYPE_SECURE = 2;
45683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected static final int SETTING_TYPE_SYSTEM = 3;
46683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
47683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected static final String FAKE_SETTING_NAME = "fake_setting_name";
48683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected static final String FAKE_SETTING_NAME_1 = "fake_setting_name1";
493a2c3578ba5bf8642c994fa357a96eaa4a38cdc9Makoto Onuki    protected static final String FAKE_SETTING_NAME_2 = "fake_setting_name2";
50683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected static final String FAKE_SETTING_VALUE = "fake_setting_value";
513a2c3578ba5bf8642c994fa357a96eaa4a38cdc9Makoto Onuki    protected static final String FAKE_SETTING_VALUE_1 = SettingsStateTest.CRAZY_STRING;
523a2c3578ba5bf8642c994fa357a96eaa4a38cdc9Makoto Onuki    protected static final String FAKE_SETTING_VALUE_2 = null;
53683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
54683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    private static final String[] NAME_VALUE_COLUMNS = new String[] {
55683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE
56683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    };
57683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
58e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    private int mSecondaryUserId = Integer.MIN_VALUE;
59683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
60683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected void setStringViaFrontEndApiSetting(int type, String name, String value, int userId) {
61683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        ContentResolver contentResolver = getContext().getContentResolver();
62683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
63683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        switch (type) {
64683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_GLOBAL: {
65683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                Settings.Global.putStringForUser(contentResolver, name, value, userId);
66683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            } break;
67683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
68683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_SECURE: {
69683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                Settings.Secure.putStringForUser(contentResolver, name, value, userId);
70683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            } break;
71683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
72683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_SYSTEM: {
73683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                Settings.System.putStringForUser(contentResolver, name, value, userId);
74683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            } break;
75683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
76683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            default: {
77683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                throw new IllegalArgumentException("Invalid type: " + type);
78683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
79683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        }
80683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    }
81683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
82683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected String getStringViaFrontEndApiSetting(int type, String name, int userId) {
83683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        ContentResolver contentResolver = getContext().getContentResolver();
84683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
85683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        switch (type) {
86683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_GLOBAL: {
87683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                return Settings.Global.getStringForUser(contentResolver, name, userId);
88683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
89683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
90683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_SECURE: {
91683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                return Settings.Secure.getStringForUser(contentResolver, name, userId);
92683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
93683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
94683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_SYSTEM: {
95683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                return Settings.System.getStringForUser(contentResolver, name, userId);
96683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
97683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
98683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            default: {
99683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                throw new IllegalArgumentException("Invalid type: " + type);
100683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
101683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        }
102683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    }
103683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
104683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected Uri insertStringViaProviderApi(int type, String name, String value,
105683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            boolean withTableRowUri) {
106683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        Uri uri = getBaseUriForType(type);
107683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        if (withTableRowUri) {
108683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            uri = Uri.withAppendedPath(uri, name);
109683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        }
110683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        ContentValues values = new ContentValues();
111683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        values.put(Settings.NameValueTable.NAME, name);
112683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        values.put(Settings.NameValueTable.VALUE, value);
113683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
114683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        return getContext().getContentResolver().insert(uri, values);
115683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    }
116683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
117683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected int deleteStringViaProviderApi(int type, String name) {
118683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        Uri uri = getBaseUriForType(type);
119683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        return getContext().getContentResolver().delete(uri, "name=?", new String[]{name});
120683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    }
121683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
122683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected int updateStringViaProviderApiSetting(int type, String name, String value) {
123683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        Uri uri = getBaseUriForType(type);
124683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        ContentValues values = new ContentValues();
125683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        values.put(Settings.NameValueTable.NAME, name);
126683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        values.put(Settings.NameValueTable.VALUE, value);
127683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        return getContext().getContentResolver().update(uri, values, "name=?",
128683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                new String[]{name});
129683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    }
130683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
131683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected String queryStringViaProviderApi(int type, String name) {
1322849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav        return queryStringViaProviderApi(type, name, false, false);
133683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    }
134683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
1352849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav    protected String queryStringViaProviderApi(int type, String name, boolean queryStringInQuotes,
1362849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav            boolean appendNameToUri) {
1372849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav        final Uri uri;
1382849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav        final String queryString;
1392849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav        final String[] queryArgs;
1402849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav
1412849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav        if (appendNameToUri) {
1422849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav            uri = Uri.withAppendedPath(getBaseUriForType(type), name);
1432849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav            queryString = null;
1442849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav            queryArgs = null;
1452849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav        } else {
1462849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav            uri = getBaseUriForType(type);
1472849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav            queryString = queryStringInQuotes ? "(name=?)" : "name=?";
1482849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav            queryArgs = new String[]{name};
1492849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav        }
150683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
151683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS,
1522849465ee19febd5135cb6ab8cb548a3c8ac6a24Svetoslav                queryString, queryArgs, null);
153683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
154683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        if (cursor == null) {
155683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            return null;
156683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        }
157683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
158683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        try {
159683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            if (cursor.moveToFirst()) {
160683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
161683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                return cursor.getString(valueColumnIdx);
162683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
163683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        } finally {
164683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            cursor.close();
165683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        }
166683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
167683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        return null;
168683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    }
169683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
170e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected static void resetSettingsViaShell(int type, int resetMode) throws IOException {
171e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        final String modeString;
172e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        switch (resetMode) {
173e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case Settings.RESET_MODE_UNTRUSTED_DEFAULTS: {
174e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                modeString = "untrusted_defaults";
175e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
176e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
177e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case Settings.RESET_MODE_UNTRUSTED_CHANGES: {
178e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                modeString = "untrusted_clear";
179e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
180e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
181e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case Settings.RESET_MODE_TRUSTED_DEFAULTS: {
182e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                modeString = "trusted_defaults";
183e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
184e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
185e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            default: {
186e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                throw new IllegalArgumentException("Invalid reset mode: " + resetMode);
187e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
188e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        }
189e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
190e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        switch (type) {
191e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_GLOBAL: {
192e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                executeShellCommand("settings reset global " + modeString);
193e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
194e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
195e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SECURE: {
196e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                executeShellCommand("settings reset secure " + modeString);
197e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
198e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
199e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            default: {
200e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                throw new IllegalArgumentException("Invalid type: " + type);
201e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
202e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        }
203e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
204e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
205e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected static void resetToDefaultsViaShell(int type, String packageName) throws IOException {
206e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        resetToDefaultsViaShell(type, packageName, null);
207e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
208e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
2095fb405ba60dc6daca54d507909b68b5ad8144920Svetoslav Ganov    protected static void resetToDefaultsViaShell(int type, String packageName, String tag)
210e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            throws IOException {
211e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        switch (type) {
212e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_GLOBAL: {
2135fb405ba60dc6daca54d507909b68b5ad8144920Svetoslav Ganov                executeShellCommand("settings reset global " + packageName + " "
2145fb405ba60dc6daca54d507909b68b5ad8144920Svetoslav Ganov                        + (tag != null ? tag : ""));
215e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
216e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
217e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SECURE: {
2185fb405ba60dc6daca54d507909b68b5ad8144920Svetoslav Ganov                executeShellCommand("settings reset secure " + packageName + " "
2195fb405ba60dc6daca54d507909b68b5ad8144920Svetoslav Ganov                        + (tag != null ? tag : ""));
220e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
221e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
222e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SYSTEM: {
2235fb405ba60dc6daca54d507909b68b5ad8144920Svetoslav Ganov                executeShellCommand("settings reset system " + packageName + " "
2245fb405ba60dc6daca54d507909b68b5ad8144920Svetoslav Ganov                        + (tag != null ? tag : ""));
225e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
226e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
227e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            default: {
228e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                throw new IllegalArgumentException("Invalid type: " + type);
229e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
230e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        }
231e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
232e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
233e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected String getSetting(int type, String name) {
234e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        switch (type) {
235e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_GLOBAL: {
236e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                return Settings.Global.getString(getContext().getContentResolver(), name);
237e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
238e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
239e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SECURE: {
240e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                return Settings.Secure.getString(getContext().getContentResolver(), name);
241e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
242e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
243e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SYSTEM: {
244e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                return Settings.System.getString(getContext().getContentResolver(), name);
245e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
246e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
247e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            default: {
248e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                throw new IllegalArgumentException("Invalid type: " + type);
249e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
250e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        }
251e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
252e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
253e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected void putSetting(int type, String name, String value) {
254e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        switch (type) {
255e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_GLOBAL: {
256e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                Settings.Global.putString(getContext().getContentResolver(), name, value);
257e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
258e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
259e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SECURE: {
260e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                Settings.Secure.putString(getContext().getContentResolver(), name, value);
261e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
262e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
263e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SYSTEM: {
264e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                Settings.System.putString(getContext().getContentResolver(), name, value);
265e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
266e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
267e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            default: {
268e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                throw new IllegalArgumentException("Invalid type: " + type);
269e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
270e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        }
271e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
272e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
273e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected static void setSettingViaShell(int type, String name, String value,
274e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            boolean makeDefault) throws IOException {
275e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        setSettingViaShell(type, name, value, null, makeDefault);
276e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
277e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
278e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected static void setSettingViaShell(int type, String name, String value,
279e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            String token, boolean makeDefault) throws IOException {
280e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        switch (type) {
281e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_GLOBAL: {
282e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                executeShellCommand("settings put global " + name + " "
283e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                        + value + (token != null ? " " + token : "")
284e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                        + (makeDefault ? " default" : ""));
285e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
286e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
287e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
288e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SECURE: {
289e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                executeShellCommand("settings put secure " + name + " "
290e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                        + value + (token != null ? " " + token : "")
291e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                        + (makeDefault ? " default" : ""));
292e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
293e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
294e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            case SETTING_TYPE_SYSTEM: {
295e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                executeShellCommand("settings put system " + name + " "
296e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                        + value + (token != null ? " " + token : "")
297e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                        + (makeDefault ? " default" : ""));
298e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            } break;
299e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
300e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            default: {
301e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                throw new IllegalArgumentException("Invalid type: " + type);
302e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
303e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        }
304e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
305e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
306e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected Context getContext() {
307e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        return InstrumentationRegistry.getContext();
308e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
309e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
310e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected int getSecondaryUserId() {
311e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        if (mSecondaryUserId == Integer.MIN_VALUE) {
312e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            UserManager userManager = (UserManager) getContext()
313e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                    .getSystemService(Context.USER_SERVICE);
314e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            List<UserInfo> users = userManager.getUsers();
315e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            final int userCount = users.size();
316e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            for (int i = 0; i < userCount; i++) {
317e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                UserInfo user = users.get(i);
318e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                if (!user.isPrimary() && !user.isManagedProfile()) {
319e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                    mSecondaryUserId = user.id;
320e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                    return mSecondaryUserId;
321e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                }
322e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            }
323e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        }
324e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        if (mSecondaryUserId == Integer.MIN_VALUE) {
325e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov            mSecondaryUserId =  UserHandle.USER_SYSTEM;
326e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        }
327e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        return mSecondaryUserId;
328e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
329e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
330683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    protected static Uri getBaseUriForType(int type) {
331683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        switch (type) {
332683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_GLOBAL: {
333683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                return Settings.Global.CONTENT_URI;
334683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
335683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
336683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_SECURE: {
337683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                return Settings.Secure.CONTENT_URI;
338683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
339683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
340683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            case SETTING_TYPE_SYSTEM: {
341683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                return Settings.System.CONTENT_URI;
342683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
343683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav
344683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            default: {
345683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav                throw new IllegalArgumentException("Invalid type: " + type);
346683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav            }
347683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav        }
348683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav    }
349e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov
350e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    protected static void executeShellCommand(String command) throws IOException {
351e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        InputStream is = new FileInputStream(InstrumentationRegistry.getInstrumentation()
352e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov                .getUiAutomation().executeShellCommand(command).getFileDescriptor());
353e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov        Streams.readFully(is);
354e080da9ee027fcd030aa92ea26fd0ed9f031674fSvetoslav Ganov    }
355683914bfb13908bf380a25258cd45bcf43f13dc9Svetoslav}
356