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

Commit 0576bd7c authored by Robert Snoeberger's avatar Robert Snoeberger
Browse files

Add activity for just clock face picker.

The activity can be started by an intent with action:
  com.google.android.apps.wallpaper.ACTIVITY_CLOCK_FACE_PICKER
When the activity finishes, it sets the ID of the selected
clock into an extra with name "clock_face_name".

Bug: 130021301
Test: Launched activity with `adb shell am start -a "com.google.android.apps.wallpaper.ACTIVITY_CLOCK_FACE_PICKER"`
Change-Id: Iea974d011b786587300564e3aa25f7e85add6fb2
Test: Checked that clock not changed on lock screen/AOD
parent a4fe9177
Loading
Loading
Loading
Loading
+29 −0
Original line number Original line Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2019 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.
-->
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

  <FrameLayout
      android:id="@+id/fragment_container"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

</FrameLayout>
+111 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2019 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.customization.model.clock;

import static junit.framework.TestCase.assertTrue;
import static junit.framework.TestCase.fail;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import androidx.annotation.Nullable;

import com.android.customization.model.CustomizationManager.Callback;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;

@RunWith(RobolectricTestRunner.class)
public class BaseClockManagerTest {

    private static final String CURRENT_CLOCK = "current_clock";

    @Mock ClockProvider mProvider;
    private TestClockManager mManager;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mManager = new TestClockManager(mProvider);
    }

    @Test
    public void testIsAvailable() {
        // GIVEN that the ClockProvider is available
        when(mProvider.isAvailable()).thenReturn(true);
        // THEN the BaseClockManager is true
        assertTrue(mManager.isAvailable());
    }

    @Test
    public void testApply() {
        final String id = "id";
        Clockface clock = new Clockface.Builder().setId(id).build();

        mManager.apply(clock, new Callback() {
            @Override
            public void onSuccess() {
                //Nothing to do here, the test passed
            }
            @Override
            public void onError(@Nullable Throwable throwable) {
                fail("onError was called when grid had been applied successfully");
            }
        });

        assertEquals(id, mManager.getClockId());
    }

    @Test
    public void testFetch() {
        mManager.fetchOptions(null, false);
        verify(mProvider).fetch(eq(null), anyBoolean());
    }

    /**
     * Testable BaseClockManager that provides basic implementations of abstract methods.
     */
    private static final class TestClockManager extends BaseClockManager {

        private String mClockId;

        TestClockManager(ClockProvider provider) {
            super(provider);
        }

        String getClockId() {
            return mClockId;
        }

        @Override
        protected void handleApply(Clockface option, Callback callback) {
            mClockId = option.getId();
            callback.onSuccess();
        }

        @Override
        protected String lookUpCurrentClock() {
            return CURRENT_CLOCK;
        }
    }
}
+84 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2019 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.customization.model.clock;

import static junit.framework.TestCase.fail;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;

import android.content.ContentResolver;
import android.provider.Settings.Secure;
import androidx.annotation.Nullable;

import com.android.customization.model.CustomizationManager.Callback;

import com.android.customization.module.ThemesUserEventLogger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

@RunWith(RobolectricTestRunner.class)
public class ClockManagerTest {

    private static final String CLOCK_ID = "id";

    @Mock ClockProvider mProvider;
    @Mock ThemesUserEventLogger mLogger;
    private ContentResolver mContentResolver;
    private ClockManager mManager;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContentResolver = RuntimeEnvironment.application.getContentResolver();
        mManager = new ClockManager(mContentResolver, mProvider, mLogger);
    }

    @Test
    public void testApply() {
        Clockface clock = new Clockface.Builder().setId(CLOCK_ID).build();

        mManager.apply(clock, new Callback() {
            @Override
            public void onSuccess() {
                //Nothing to do here, the test passed
            }

            @Override
            public void onError(@Nullable Throwable throwable) {
                fail("onError was called when grid had been applied successfully");
            }
        });

        // THEN the clock id is written to secure settings.
        assertEquals(CLOCK_ID, Secure.getString(mContentResolver, ClockManager.CLOCK_FACE_SETTING));
        // AND the event is logged
        verify(mLogger).logClockApplied(clock);
    }

    @Test
    public void testGetCurrentClock() {
        // GIVEN that secure settings contains a clock id
        Secure.putString(mContentResolver, ClockManager.CLOCK_FACE_SETTING, CLOCK_ID);
        // THEN the current clock is that id
        assertEquals(CLOCK_ID, mManager.getCurrentClock());
    }
}
+65 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2019 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.customization.model.clock;

import com.android.customization.model.CustomizationManager;

/**
 * {@link CustomizationManager} for clock faces.
 */
public abstract class BaseClockManager implements CustomizationManager<Clockface> {

    private final ClockProvider mClockProvider;

    public BaseClockManager(ClockProvider provider) {
        mClockProvider = provider;
    }

    @Override
    public boolean isAvailable() {
        return mClockProvider.isAvailable();
    }

    @Override
    public void apply(Clockface option, Callback callback) {
        handleApply(option, callback);
    }

    @Override
    public void fetchOptions(OptionsFetchedListener<Clockface> callback, boolean reload) {
        mClockProvider.fetch(callback, false);
    }

    /** Returns the ID of the current clock face, which may be null for the default clock face. */
    String getCurrentClock() {
        return lookUpCurrentClock();
    }

    /**
     * Implement to apply the clock picked by the user for {@link BaseClockManager#apply}.
     *
     * @param option Clock option, containing ID of the clock, that the user picked.
     * @param callback Report success and failure.
     */
    protected abstract void handleApply(Clockface option, Callback callback);

    /**
     * Implement to look up the current clock face for {@link BaseClockManager#getCurrentClock()}.
     *
     * @return ID of current clock. Can be null for the default clock face.
     */
    protected abstract String lookUpCurrentClock();
}
+15 −23
Original line number Original line Diff line number Diff line
@@ -15,35 +15,31 @@
 */
 */
package com.android.customization.model.clock;
package com.android.customization.model.clock;


import android.content.Context;
import android.content.ContentResolver;
import android.provider.Settings.Secure;
import android.provider.Settings.Secure;


import com.android.customization.model.CustomizationManager;
import com.android.customization.module.ThemesUserEventLogger;
import com.android.customization.module.ThemesUserEventLogger;


public class ClockManager implements CustomizationManager<Clockface> {
/**
 * {@link CustomizationManager} for clock faces that implements apply by writing to secure settings.
 */
public class ClockManager extends BaseClockManager {


    // TODO: use constant from Settings.Secure
    // TODO: use constant from Settings.Secure
    private static final String CLOCK_FACE_SETTING = "lock_screen_custom_clock_face";
    static final String CLOCK_FACE_SETTING = "lock_screen_custom_clock_face";
    private final ClockProvider mClockProvider;
    private final ContentResolver mContentResolver;
    private final Context mContext;
    private final ThemesUserEventLogger mEventLogger;
    private final ThemesUserEventLogger mEventLogger;


    public ClockManager(Context context, ClockProvider provider, ThemesUserEventLogger logger) {
    public ClockManager(ContentResolver resolver, ClockProvider provider,
        mClockProvider = provider;
            ThemesUserEventLogger logger) {
        mContext = context;
        super(provider);
        mContentResolver = resolver;
        mEventLogger = logger;
        mEventLogger = logger;
    }
    }


    @Override
    @Override
    public boolean isAvailable() {
    protected void handleApply(Clockface option, Callback callback) {
        return mClockProvider.isAvailable();
        boolean stored = Secure.putString(mContentResolver, CLOCK_FACE_SETTING, option.getId());
    }

    @Override
    public void apply(Clockface option, Callback callback) {
        boolean stored = Secure.putString(mContext.getContentResolver(),
                CLOCK_FACE_SETTING, option.getId());
        if (stored) {
        if (stored) {
            mEventLogger.logClockApplied(option);
            mEventLogger.logClockApplied(option);
            callback.onSuccess();
            callback.onSuccess();
@@ -53,11 +49,7 @@ public class ClockManager implements CustomizationManager<Clockface> {
    }
    }


    @Override
    @Override
    public void fetchOptions(OptionsFetchedListener<Clockface> callback, boolean reload) {
    protected String lookUpCurrentClock() {
        mClockProvider.fetch(callback, false);
        return Secure.getString(mContentResolver, CLOCK_FACE_SETTING);
    }

    public String getCurrentClock() {
        return Secure.getString(mContext.getContentResolver(), CLOCK_FACE_SETTING);
    }
    }
}
}
Loading