OSDN Git Service

Adds unit tests in attention manager service for two interfaces:
authorYi Jiang <eejiang@google.com>
Wed, 10 Apr 2019 20:36:27 +0000 (13:36 -0700)
committerAlex Salo <asalo@google.com>
Tue, 16 Apr 2019 17:45:01 +0000 (17:45 +0000)
-checkAttention()
-cancelAttentionCheck()

Bug: 128918890
Test: atest AttentionManagerServiceTest
Change-Id: I0ca0029526e6254881d546728e64d53a04e60b93

services/core/java/com/android/server/attention/AttentionManagerService.java
services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java [new file with mode: 0644]

index 411dd79..d7d4851 100644 (file)
@@ -58,6 +58,7 @@ import android.util.StatsLog;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
@@ -100,16 +101,25 @@ public class AttentionManagerService extends SystemService {
     private final Object mLock;
     @GuardedBy("mLock")
     private final SparseArray<UserState> mUserStates = new SparseArray<>();
-    private final AttentionHandler mAttentionHandler;
+    private AttentionHandler mAttentionHandler;
 
-    private ComponentName mComponentName;
+    @VisibleForTesting
+    ComponentName mComponentName;
 
     public AttentionManagerService(Context context) {
+        this(context, (PowerManager) context.getSystemService(Context.POWER_SERVICE),
+                new Object(), null);
+        mAttentionHandler = new AttentionHandler();
+    }
+
+    @VisibleForTesting
+    AttentionManagerService(Context context, PowerManager powerManager, Object lock,
+            AttentionHandler handler) {
         super(context);
         mContext = Preconditions.checkNotNull(context);
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mLock = new Object();
-        mAttentionHandler = new AttentionHandler();
+        mPowerManager = powerManager;
+        mLock = lock;
+        mAttentionHandler = handler;
     }
 
     @Override
@@ -147,7 +157,8 @@ public class AttentionManagerService extends SystemService {
         return isServiceEnabled() && isServiceAvailable();
     }
 
-    private boolean isServiceEnabled() {
+    @VisibleForTesting
+    protected boolean isServiceEnabled() {
         return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE, SERVICE_ENABLED,
                 DEFAULT_SERVICE_ENABLED);
     }
@@ -161,7 +172,8 @@ public class AttentionManagerService extends SystemService {
      *
      * @return {@code true} if the framework was able to dispatch the request
      */
-    private boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
+    @VisibleForTesting
+    boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
         Preconditions.checkNotNull(callbackInternal);
 
         if (!isAttentionServiceSupported()) {
@@ -257,24 +269,24 @@ public class AttentionManagerService extends SystemService {
     }
 
     /** Cancels the specified attention check. */
-    private void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
+    @VisibleForTesting
+    void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
         synchronized (mLock) {
             final UserState userState = peekCurrentUserStateLocked();
             if (userState == null) {
                 return;
             }
-
             if (!userState.mCurrentAttentionCheck.mCallbackInternal.equals(callbackInternal)) {
                 Slog.e(LOG_TAG, "Cannot cancel a non-current request");
                 return;
             }
-
             cancel(userState);
         }
     }
 
     @GuardedBy("mLock")
-    private void freeIfInactiveLocked() {
+    @VisibleForTesting
+    protected void freeIfInactiveLocked() {
         // If we are called here, it means someone used the API again - reset the timer then.
         mAttentionHandler.removeMessages(AttentionHandler.CHECK_CONNECTION_EXPIRATION);
 
@@ -291,7 +303,8 @@ public class AttentionManagerService extends SystemService {
 
 
     @GuardedBy("mLock")
-    private UserState getOrCreateCurrentUserStateLocked() {
+    @VisibleForTesting
+    protected UserState getOrCreateCurrentUserStateLocked() {
         return getOrCreateUserStateLocked(ActivityManager.getCurrentUser());
     }
 
@@ -307,7 +320,8 @@ public class AttentionManagerService extends SystemService {
 
     @GuardedBy("mLock")
     @Nullable
-    private UserState peekCurrentUserStateLocked() {
+    @VisibleForTesting
+    protected UserState peekCurrentUserStateLocked() {
         return peekUserStateLocked(ActivityManager.getCurrentUser());
     }
 
@@ -418,7 +432,8 @@ public class AttentionManagerService extends SystemService {
         }
     }
 
-    private static final class AttentionCheck {
+    @VisibleForTesting
+    static final class AttentionCheck {
         private final AttentionCallbackInternal mCallbackInternal;
         private final IAttentionCallback mIAttentionCallback;
         private boolean mIsDispatched;
@@ -435,7 +450,8 @@ public class AttentionManagerService extends SystemService {
         }
     }
 
-    private static final class UserState {
+    @VisibleForTesting
+    protected static class UserState {
         final ComponentName mComponentName;
         final AttentionServiceConnection mConnection = new AttentionServiceConnection();
 
@@ -453,7 +469,7 @@ public class AttentionManagerService extends SystemService {
         final Context mContext;
         final Object mLock;
 
-        private UserState(int userId, Context context, Object lock, ComponentName componentName) {
+        UserState(int userId, Context context, Object lock, ComponentName componentName) {
             mUserId = userId;
             mContext = Preconditions.checkNotNull(context);
             mLock = Preconditions.checkNotNull(lock);
@@ -509,7 +525,7 @@ public class AttentionManagerService extends SystemService {
             }
         }
 
-        private final class AttentionServiceConnection implements ServiceConnection {
+        private class AttentionServiceConnection implements ServiceConnection {
             @Override
             public void onServiceConnected(ComponentName name, IBinder service) {
                 init(IAttentionService.Stub.asInterface(service));
@@ -544,7 +560,8 @@ public class AttentionManagerService extends SystemService {
         }
     }
 
-    private class AttentionHandler extends Handler {
+    @VisibleForTesting
+    protected class AttentionHandler extends Handler {
         private static final int CHECK_CONNECTION_EXPIRATION = 1;
         private static final int ATTENTION_CHECK_TIMEOUT = 2;
 
@@ -576,7 +593,8 @@ public class AttentionManagerService extends SystemService {
         }
     }
 
-    private void cancel(UserState userState) {
+    @VisibleForTesting
+    void cancel(UserState userState) {
         if (userState == null || userState.mCurrentAttentionCheck == null) {
             return;
         }
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
new file mode 100644 (file)
index 0000000..8426a0b
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * 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.server.attention;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IPowerManager;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.service.attention.IAttentionCallback;
+import android.service.attention.IAttentionService;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.attention.AttentionManagerService.AttentionCheck;
+import com.android.server.attention.AttentionManagerService.AttentionHandler;
+import com.android.server.attention.AttentionManagerService.UserState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link com.android.server.attention.AttentionManagerService}
+ */
+@SmallTest
+public class AttentionManagerServiceTest {
+    private AttentionManagerService mSpyAttentionManager;
+    private UserState mSpyUserState;
+    private final int mTimeout = 1000;
+    @Mock private AttentionCallbackInternal mMockAttentionCallbackInternal;
+    @Mock private AttentionHandler mMockHandler;
+    @Mock private IAttentionCallback mMockIAttentionCallback;
+    @Mock private IPowerManager mMockIPowerManager;
+    @Mock Context mContext;
+
+    @Before
+    public void setUp() throws RemoteException {
+        MockitoAnnotations.initMocks(this);
+        // setup context mock
+        doReturn(true).when(mContext).bindServiceAsUser(any(), any(), anyInt(), any());
+        // setup power manager mock
+        PowerManager mPowerManager;
+        doReturn(true).when(mMockIPowerManager).isInteractive();
+        mPowerManager = new PowerManager(mContext, mMockIPowerManager, null);
+
+        Object mLock = new Object();
+        // setup a spy on attention manager
+        AttentionManagerService mAttentionManager = new AttentionManagerService(
+                mContext,
+                mPowerManager,
+                mLock,
+                mMockHandler);
+        mSpyAttentionManager = Mockito.spy(mAttentionManager);
+        // setup a spy on user state
+        ComponentName componentName = new ComponentName("a", "b");
+        mSpyAttentionManager.mComponentName = componentName;
+        UserState mUserState = new UserState(0,
+                mContext,
+                mLock,
+                componentName);
+        mUserState.mService = new MockIAttentionService();
+        mSpyUserState = spy(mUserState);
+    }
+
+    @Test
+    public void testCancelAttentionCheck_noCrashWhenNoUserStateLocked() {
+        mSpyAttentionManager.cancelAttentionCheck(null);
+    }
+
+    @Test
+    public void testCancelAttentionCheck_noCrashWhenCallbackMismatched() {
+        mSpyUserState.mCurrentAttentionCheck =
+                new AttentionCheck(mMockAttentionCallbackInternal, mMockIAttentionCallback);
+        doReturn(mSpyUserState).when(mSpyAttentionManager).peekCurrentUserStateLocked();
+        mSpyAttentionManager.cancelAttentionCheck(null);
+    }
+
+    @Test
+    public void testCancelAttentionCheck_cancelCallbackWhenMatched() {
+        mSpyUserState.mCurrentAttentionCheck =
+                new AttentionCheck(mMockAttentionCallbackInternal, mMockIAttentionCallback);
+        doReturn(mSpyUserState).when(mSpyAttentionManager).peekCurrentUserStateLocked();
+        mSpyAttentionManager.cancelAttentionCheck(mMockAttentionCallbackInternal);
+        verify(mSpyAttentionManager).cancel(any());
+    }
+
+    @Test
+    public void testCheckAttention_returnFalseWhenPowerManagerNotInteract() throws RemoteException {
+        doReturn(false).when(mMockIPowerManager).isInteractive();
+        AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
+        assertThat(mSpyAttentionManager.checkAttention(mTimeout, callback)).isFalse();
+    }
+
+    @Test
+    public void testCheckAttention_callOnSuccess() throws RemoteException {
+        doReturn(true).when(mSpyAttentionManager).isServiceEnabled();
+        doReturn(true).when(mMockIPowerManager).isInteractive();
+        doReturn(mSpyUserState).when(mSpyAttentionManager).getOrCreateCurrentUserStateLocked();
+        doNothing().when(mSpyAttentionManager).freeIfInactiveLocked();
+
+        AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
+        mSpyAttentionManager.checkAttention(mTimeout, callback);
+        verify(callback).onSuccess(anyInt(), anyLong());
+    }
+
+    private class MockIAttentionService implements IAttentionService {
+        public void checkAttention(IAttentionCallback callback) throws RemoteException {
+            callback.onSuccess(0, 0);
+        }
+        public void cancelAttentionCheck(IAttentionCallback callback) {
+        }
+        public IBinder asBinder() {
+            return null;
+        }
+    }
+}