| /* |
| * Copyright (C) 2022 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.server; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import android.content.Intent; |
| import android.os.Looper; |
| import android.testing.AndroidTestingRunner; |
| import android.testing.TestableContext; |
| import android.testing.TestableLooper; |
| |
| import androidx.test.core.app.ApplicationProvider; |
| |
| import com.android.internal.R; |
| import com.android.internal.util.test.BroadcastInterceptingContext; |
| |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.concurrent.ExecutionException; |
| |
| @RunWith(AndroidTestingRunner.class) |
| @TestableLooper.RunWithLooper |
| public class DockObserverTest { |
| |
| @Rule |
| public TestableContext mContext = |
| new TestableContext(ApplicationProvider.getApplicationContext(), null); |
| |
| private final BroadcastInterceptingContext mInterceptingContext = |
| new BroadcastInterceptingContext(mContext); |
| |
| BroadcastInterceptingContext.FutureIntent updateExtconDockState(DockObserver observer, |
| String extconDockState) { |
| BroadcastInterceptingContext.FutureIntent futureIntent = |
| mInterceptingContext.nextBroadcastIntent(Intent.ACTION_DOCK_EVENT); |
| observer.setDockStateFromProviderForTesting( |
| DockObserver.ExtconStateProvider.fromString(extconDockState)); |
| TestableLooper.get(this).processAllMessages(); |
| return futureIntent; |
| } |
| |
| DockObserver observerWithMappingConfig(String[] configEntries) { |
| mContext.getOrCreateTestableResources().addOverride( |
| R.array.config_dockExtconStateMapping, |
| configEntries); |
| return new DockObserver(mInterceptingContext); |
| } |
| |
| void assertDockEventIntentWithExtraThenUndock(DockObserver observer, String extconDockState, |
| int expectedExtra) throws ExecutionException, InterruptedException { |
| assertThat(updateExtconDockState(observer, extconDockState) |
| .get().getIntExtra(Intent.EXTRA_DOCK_STATE, -1)) |
| .isEqualTo(expectedExtra); |
| assertThat(updateExtconDockState(observer, "DOCK=0") |
| .get().getIntExtra(Intent.EXTRA_DOCK_STATE, -1)) |
| .isEqualTo(Intent.EXTRA_DOCK_STATE_UNDOCKED); |
| } |
| |
| @Before |
| public void setUp() { |
| if (Looper.myLooper() == null) { |
| Looper.prepare(); |
| } |
| } |
| |
| @Test |
| public void testDockIntentBroadcast_onlyAfterBootReady() |
| throws ExecutionException, InterruptedException { |
| DockObserver observer = new DockObserver(mInterceptingContext); |
| BroadcastInterceptingContext.FutureIntent futureIntent = |
| updateExtconDockState(observer, "DOCK=1"); |
| updateExtconDockState(observer, "DOCK=1").assertNotReceived(); |
| // Last boot phase reached |
| observer.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); |
| TestableLooper.get(this).processAllMessages(); |
| assertThat(futureIntent.get().getIntExtra(Intent.EXTRA_DOCK_STATE, -1)) |
| .isEqualTo(Intent.EXTRA_DOCK_STATE_DESK); |
| } |
| |
| @Test |
| public void testDockIntentBroadcast_customConfigResource() |
| throws ExecutionException, InterruptedException { |
| DockObserver observer = observerWithMappingConfig( |
| new String[] {"2,KEY1=1,KEY2=2", "3,KEY3=3"}); |
| observer.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); |
| |
| // Mapping should not match |
| assertDockEventIntentWithExtraThenUndock(observer, "DOCK=1", |
| Intent.EXTRA_DOCK_STATE_DESK); |
| assertDockEventIntentWithExtraThenUndock(observer, "DOCK=1\nKEY1=1", |
| Intent.EXTRA_DOCK_STATE_DESK); |
| assertDockEventIntentWithExtraThenUndock(observer, "DOCK=1\nKEY2=2", |
| Intent.EXTRA_DOCK_STATE_DESK); |
| |
| // 1st mapping now matches |
| assertDockEventIntentWithExtraThenUndock(observer, "DOCK=1\nKEY2=2\nKEY1=1", |
| Intent.EXTRA_DOCK_STATE_CAR); |
| |
| // 2nd mapping now matches |
| assertDockEventIntentWithExtraThenUndock(observer, "DOCK=1\nKEY3=3", |
| Intent.EXTRA_DOCK_STATE_LE_DESK); |
| } |
| |
| @Test |
| public void testDockIntentBroadcast_customConfigResourceWithWildcard() |
| throws ExecutionException, InterruptedException { |
| DockObserver observer = observerWithMappingConfig(new String[] { |
| "2,KEY2=2", |
| "3,KEY3=3", |
| "4" |
| }); |
| observer.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); |
| assertDockEventIntentWithExtraThenUndock(observer, "DOCK=1\nKEY5=5", |
| Intent.EXTRA_DOCK_STATE_HE_DESK); |
| } |
| } |