Loading core/java/com/android/internal/util/WakeupMessage.java +12 −4 Original line number Diff line number Diff line Loading @@ -45,24 +45,32 @@ public class WakeupMessage implements AlarmManager.OnAlarmListener { protected final String mCmdName; @VisibleForTesting protected final int mCmd, mArg1, mArg2; @VisibleForTesting protected final Object mObj; private boolean mScheduled; public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1, int arg2) { String cmdName, int cmd, int arg1, int arg2, Object obj) { mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); mHandler = handler; mCmdName = cmdName; mCmd = cmd; mArg1 = arg1; mArg2 = arg2; mObj = obj; } public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1) { this(context, handler, cmdName, cmd, arg1, 0); this(context, handler, cmdName, cmd, arg1, 0, null); } public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1, int arg2) { this(context, handler, cmdName, cmd, arg1, arg2, null); } public WakeupMessage(Context context, Handler handler, String cmdName, int cmd) { this(context, handler, cmdName, cmd, 0, 0); this(context, handler, cmdName, cmd, 0, 0, null); } /** Loading Loading @@ -99,7 +107,7 @@ public class WakeupMessage implements AlarmManager.OnAlarmListener { mScheduled = false; } if (stillScheduled) { Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2); Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj); mHandler.handleMessage(msg); msg.recycle(); } Loading core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ public class WakeupMessageTest { private static final int TEST_CMD = 18; private static final int TEST_ARG1 = 33; private static final int TEST_ARG2 = 182; private static final Object TEST_OBJ = "hello"; @Mock AlarmManager mAlarmManager; WakeupMessage mMessage; Loading Loading @@ -92,7 +93,7 @@ public class WakeupMessageTest { mListenerCaptor.capture(), any(Handler.class)); mMessage = new WakeupMessage(context, mHandler, TEST_CMD_NAME, TEST_CMD, TEST_ARG1, TEST_ARG2); TEST_ARG2, TEST_OBJ); } /** Loading @@ -114,6 +115,7 @@ public class WakeupMessageTest { assertEquals("what", TEST_CMD, mHandler.getLastMessage().what); assertEquals("arg1", TEST_ARG1, mHandler.getLastMessage().arg1); assertEquals("arg2", TEST_ARG2, mHandler.getLastMessage().arg2); assertEquals("obj", TEST_OBJ, mHandler.getLastMessage().obj); } /** Loading services/core/java/com/android/server/ConnectivityService.java +11 −0 Original line number Diff line number Diff line Loading @@ -797,6 +797,17 @@ public class ConnectivityService extends IConnectivityManager.Stub return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId()); } // Used only for testing. // TODO: Delete this and either: // 1. Give Fake SettingsProvider the ability to send settings change notifications (requires // changing ContentResolver to make registerContentObserver non-final). // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it // by subclassing SettingsObserver. @VisibleForTesting void updateMobileDataAlwaysOn() { mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON); } private void handleMobileDataAlwaysOn() { final boolean enable = (Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1); Loading services/tests/servicestests/src/com/android/internal/util/FakeSettingsProvider.java 0 → 100644 +130 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 com.android.internal.util; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.test.mock.MockContentProvider; import android.util.Log; import java.util.HashMap; /** * Fake for system settings. * * To use, ensure that the Context used by the test code returns a ContentResolver that uses this * provider for the Settings authority: * * class MyTestContext extends MockContext { * ... * private final MockContentResolver mContentResolver; * public MyTestContext(...) { * ... * mContentResolver = new MockContentResolver(); * mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); * } * ... * @Override * public ContentResolver getContentResolver() { * return mContentResolver; * } * * As long as the code under test is using the test Context, the actual code under test does not * need to be modified, and can access Settings using the normal static methods: * * Settings.Global.getInt(cr, "my_setting", 0); // Returns 0. * Settings.Global.putInt(cr, "my_setting", 5); * Settings.Global.getInt(cr, "my_setting", 0); // Returns 5. * * Note that this class cannot be used in the same process as real settings. This is because it * works by passing an alternate ContentResolver to Settings operations. Unfortunately, the Settings * class only fetches the content provider from the passed-in ContentResolver the first time it's * used, and after that stores it in a per-process static. * * TODO: evaluate implementing settings change notifications. This would require: * * 1. Making ContentResolver#registerContentObserver non-final and overriding it in * MockContentResolver. * 2. Making FakeSettingsProvider take a ContentResolver argument. * 3. Calling ContentResolver#notifyChange(getUriFor(table, arg), ...) on every settings change. */ public class FakeSettingsProvider extends MockContentProvider { private static final String TAG = FakeSettingsProvider.class.getSimpleName(); private static final boolean DBG = false; private static final String[] TABLES = { "system", "secure", "global" }; private final HashMap<String, HashMap<String, String>> mTables = new HashMap<>(); public FakeSettingsProvider() { for (int i = 0; i < TABLES.length; i++) { mTables.put(TABLES[i], new HashMap<String, String>()); } } private Uri getUriFor(String table, String key) { switch (table) { case "system": return Settings.System.getUriFor(key); case "secure": return Settings.Secure.getUriFor(key); case "global": return Settings.Global.getUriFor(key); default: throw new UnsupportedOperationException("Unknown settings table " + table); } } public Bundle call(String method, String arg, Bundle extras) { // Methods are "GET_system", "GET_global", "PUT_secure", etc. String[] commands = method.split("_", 2); String op = commands[0]; String table = commands[1]; Bundle out = new Bundle(); String value; switch (op) { case "GET": value = mTables.get(table).get(arg); if (value != null) { if (DBG) { Log.d(TAG, String.format("Returning fake setting %s.%s = %s", table, arg, value)); } out.putString(Settings.NameValueTable.VALUE, value); } break; case "PUT": value = extras.getString(Settings.NameValueTable.VALUE, null); if (DBG) { Log.d(TAG, String.format("Inserting fake setting %s.%s = %s", table, arg, value)); } if (value != null) { mTables.get(table).put(arg, value); } else { mTables.get(table).remove(arg); } break; default: throw new UnsupportedOperationException("Unknown command " + method); } return out; } } services/tests/servicestests/src/com/android/internal/util/FakeSettingsProviderTest.java 0 → 100644 +58 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 com.android.internal.util; import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; import android.test.AndroidTestCase; import android.test.mock.MockContentResolver; import android.test.mock.MockContext; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Unit tests for FakeSettingsProvider. */ public class FakeSettingsProviderTest extends AndroidTestCase { private MockContentResolver mCr; @Override public void setUp() throws Exception { mCr = new MockContentResolver(); mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); } @SmallTest public void testBasicOperation() throws Exception { String settingName = Settings.System.SCREEN_BRIGHTNESS; try { Settings.System.getInt(mCr, settingName); fail("FakeSettingsProvider should start off empty."); } catch (Settings.SettingNotFoundException expected) {} // Check that fake settings can be written and read back. Settings.System.putInt(mCr, settingName, 123); assertEquals(123, Settings.System.getInt(mCr, settingName)); } } Loading
core/java/com/android/internal/util/WakeupMessage.java +12 −4 Original line number Diff line number Diff line Loading @@ -45,24 +45,32 @@ public class WakeupMessage implements AlarmManager.OnAlarmListener { protected final String mCmdName; @VisibleForTesting protected final int mCmd, mArg1, mArg2; @VisibleForTesting protected final Object mObj; private boolean mScheduled; public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1, int arg2) { String cmdName, int cmd, int arg1, int arg2, Object obj) { mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); mHandler = handler; mCmdName = cmdName; mCmd = cmd; mArg1 = arg1; mArg2 = arg2; mObj = obj; } public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1) { this(context, handler, cmdName, cmd, arg1, 0); this(context, handler, cmdName, cmd, arg1, 0, null); } public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1, int arg2) { this(context, handler, cmdName, cmd, arg1, arg2, null); } public WakeupMessage(Context context, Handler handler, String cmdName, int cmd) { this(context, handler, cmdName, cmd, 0, 0); this(context, handler, cmdName, cmd, 0, 0, null); } /** Loading Loading @@ -99,7 +107,7 @@ public class WakeupMessage implements AlarmManager.OnAlarmListener { mScheduled = false; } if (stillScheduled) { Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2); Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj); mHandler.handleMessage(msg); msg.recycle(); } Loading
core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ public class WakeupMessageTest { private static final int TEST_CMD = 18; private static final int TEST_ARG1 = 33; private static final int TEST_ARG2 = 182; private static final Object TEST_OBJ = "hello"; @Mock AlarmManager mAlarmManager; WakeupMessage mMessage; Loading Loading @@ -92,7 +93,7 @@ public class WakeupMessageTest { mListenerCaptor.capture(), any(Handler.class)); mMessage = new WakeupMessage(context, mHandler, TEST_CMD_NAME, TEST_CMD, TEST_ARG1, TEST_ARG2); TEST_ARG2, TEST_OBJ); } /** Loading @@ -114,6 +115,7 @@ public class WakeupMessageTest { assertEquals("what", TEST_CMD, mHandler.getLastMessage().what); assertEquals("arg1", TEST_ARG1, mHandler.getLastMessage().arg1); assertEquals("arg2", TEST_ARG2, mHandler.getLastMessage().arg2); assertEquals("obj", TEST_OBJ, mHandler.getLastMessage().obj); } /** Loading
services/core/java/com/android/server/ConnectivityService.java +11 −0 Original line number Diff line number Diff line Loading @@ -797,6 +797,17 @@ public class ConnectivityService extends IConnectivityManager.Stub return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId()); } // Used only for testing. // TODO: Delete this and either: // 1. Give Fake SettingsProvider the ability to send settings change notifications (requires // changing ContentResolver to make registerContentObserver non-final). // 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it // by subclassing SettingsObserver. @VisibleForTesting void updateMobileDataAlwaysOn() { mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON); } private void handleMobileDataAlwaysOn() { final boolean enable = (Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1); Loading
services/tests/servicestests/src/com/android/internal/util/FakeSettingsProvider.java 0 → 100644 +130 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 com.android.internal.util; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.test.mock.MockContentProvider; import android.util.Log; import java.util.HashMap; /** * Fake for system settings. * * To use, ensure that the Context used by the test code returns a ContentResolver that uses this * provider for the Settings authority: * * class MyTestContext extends MockContext { * ... * private final MockContentResolver mContentResolver; * public MyTestContext(...) { * ... * mContentResolver = new MockContentResolver(); * mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); * } * ... * @Override * public ContentResolver getContentResolver() { * return mContentResolver; * } * * As long as the code under test is using the test Context, the actual code under test does not * need to be modified, and can access Settings using the normal static methods: * * Settings.Global.getInt(cr, "my_setting", 0); // Returns 0. * Settings.Global.putInt(cr, "my_setting", 5); * Settings.Global.getInt(cr, "my_setting", 0); // Returns 5. * * Note that this class cannot be used in the same process as real settings. This is because it * works by passing an alternate ContentResolver to Settings operations. Unfortunately, the Settings * class only fetches the content provider from the passed-in ContentResolver the first time it's * used, and after that stores it in a per-process static. * * TODO: evaluate implementing settings change notifications. This would require: * * 1. Making ContentResolver#registerContentObserver non-final and overriding it in * MockContentResolver. * 2. Making FakeSettingsProvider take a ContentResolver argument. * 3. Calling ContentResolver#notifyChange(getUriFor(table, arg), ...) on every settings change. */ public class FakeSettingsProvider extends MockContentProvider { private static final String TAG = FakeSettingsProvider.class.getSimpleName(); private static final boolean DBG = false; private static final String[] TABLES = { "system", "secure", "global" }; private final HashMap<String, HashMap<String, String>> mTables = new HashMap<>(); public FakeSettingsProvider() { for (int i = 0; i < TABLES.length; i++) { mTables.put(TABLES[i], new HashMap<String, String>()); } } private Uri getUriFor(String table, String key) { switch (table) { case "system": return Settings.System.getUriFor(key); case "secure": return Settings.Secure.getUriFor(key); case "global": return Settings.Global.getUriFor(key); default: throw new UnsupportedOperationException("Unknown settings table " + table); } } public Bundle call(String method, String arg, Bundle extras) { // Methods are "GET_system", "GET_global", "PUT_secure", etc. String[] commands = method.split("_", 2); String op = commands[0]; String table = commands[1]; Bundle out = new Bundle(); String value; switch (op) { case "GET": value = mTables.get(table).get(arg); if (value != null) { if (DBG) { Log.d(TAG, String.format("Returning fake setting %s.%s = %s", table, arg, value)); } out.putString(Settings.NameValueTable.VALUE, value); } break; case "PUT": value = extras.getString(Settings.NameValueTable.VALUE, null); if (DBG) { Log.d(TAG, String.format("Inserting fake setting %s.%s = %s", table, arg, value)); } if (value != null) { mTables.get(table).put(arg, value); } else { mTables.get(table).remove(arg); } break; default: throw new UnsupportedOperationException("Unknown command " + method); } return out; } }
services/tests/servicestests/src/com/android/internal/util/FakeSettingsProviderTest.java 0 → 100644 +58 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 com.android.internal.util; import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; import android.test.AndroidTestCase; import android.test.mock.MockContentResolver; import android.test.mock.MockContext; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Unit tests for FakeSettingsProvider. */ public class FakeSettingsProviderTest extends AndroidTestCase { private MockContentResolver mCr; @Override public void setUp() throws Exception { mCr = new MockContentResolver(); mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); } @SmallTest public void testBasicOperation() throws Exception { String settingName = Settings.System.SCREEN_BRIGHTNESS; try { Settings.System.getInt(mCr, settingName); fail("FakeSettingsProvider should start off empty."); } catch (Settings.SettingNotFoundException expected) {} // Check that fake settings can be written and read back. Settings.System.putInt(mCr, settingName, 123); assertEquals(123, Settings.System.getInt(mCr, settingName)); } }