Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e2bfbd1 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Ic98e3bcb,Idb0c55fc,Ia8649061,I5e7e5a87 into nyc-mr1-dev

* changes:
  Give WakeupMessage the ability to transport an object as well.
  Don't treat the lingerExpired broadcast specially.
  Add a test for mobile data always on.
  Add a FakeSettingsProvider and use it in ConnectivityServiceTest.
parents 5c32d65e eab17da5
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -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);
    }

    /**
@@ -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();
        }
+3 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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);
    }

    /**
@@ -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);
    }

    /**
+11 −0
Original line number Diff line number Diff line
@@ -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);
+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;
    }
}
+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