109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki/*
209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * Copyright (C) 2017 The Android Open Source Project
309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki *
409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License");
509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * you may not use this file except in compliance with the License.
609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * You may obtain a copy of the License at
709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki *
809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki *      http://www.apache.org/licenses/LICENSE-2.0
909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki *
1009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * Unless required by applicable law or agreed to in writing, software
1109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS,
1209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * See the License for the specific language governing permissions and
1409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki * limitations under the License.
1509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki */
1609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukipackage com.android.server.am;
1709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
1809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport static org.mockito.ArgumentMatchers.any;
1909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport static org.mockito.ArgumentMatchers.anyInt;
2009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport static org.mockito.ArgumentMatchers.eq;
2109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport static org.mockito.Mockito.mock;
2209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport static org.mockito.Mockito.verify;
2309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport static org.mockito.Mockito.when;
2409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
2509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.app.admin.IDeviceAdminService;
2609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.content.ComponentName;
2709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.content.Context;
2809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.content.Intent;
2909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.content.ServiceConnection;
3009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.os.Handler;
3109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.os.IBinder;
3209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.os.Looper;
3309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.os.UserHandle;
3409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.test.AndroidTestCase;
3509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport android.util.Pair;
3609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
3709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport org.mockito.ArgumentMatchers;
3809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
3909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport java.util.ArrayList;
4009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport java.util.Arrays;
4109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukiimport java.util.Collections;
4209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
4309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onukipublic class PersistentConnectionTest extends AndroidTestCase {
4409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki    private static class MyConnection extends PersistentConnection<IDeviceAdminService> {
4509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        public long uptimeMillis = 12345;
4609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
4709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        public ArrayList<Pair<Runnable, Long>> scheduledRunnables = new ArrayList<>();
4809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
4909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        public MyConnection(String tag, Context context, Handler handler, int userId,
5009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                ComponentName componentName, long rebindBackoffSeconds,
5109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                double rebindBackoffIncrease, long rebindMaxBackoffSeconds) {
5209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            super(tag, context, handler, userId, componentName,
5309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                    rebindBackoffSeconds, rebindBackoffIncrease, rebindMaxBackoffSeconds);
5409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        }
5509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
5609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        @Override
5709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        protected IDeviceAdminService asInterface(IBinder binder) {
5809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            return (IDeviceAdminService) binder;
5909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        }
6009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
6109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        @Override
6209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        long injectUptimeMillis() {
6309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            return uptimeMillis;
6409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        }
6509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
6609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        @Override
6709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        void injectPostAtTime(Runnable r, long uptimeMillis) {
6809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            scheduledRunnables.add(Pair.create(r, uptimeMillis));
6909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        }
7009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
7109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        @Override
7209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        void injectRemoveCallbacks(Runnable r) {
7309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            for (int i = scheduledRunnables.size() - 1; i >= 0; i--) {
7409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                if (scheduledRunnables.get(i).first.equals(r)) {
7509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                    scheduledRunnables.remove(i);
7609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                }
7709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            }
7809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        }
7909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
8009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        void elapse(long milliSeconds) {
8109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            uptimeMillis += milliSeconds;
8209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
8309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            // Fire the scheduled runnables.
8409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
8509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            // Note we collect first and then run all, because sometimes a scheduled runnable
8609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            // calls removeCallbacks.
8709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            final ArrayList<Runnable> list = new ArrayList<>();
8809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
8909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            for (int i = scheduledRunnables.size() - 1; i >= 0; i--) {
9009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                if (scheduledRunnables.get(i).second <= uptimeMillis) {
9109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                    list.add(scheduledRunnables.get(i).first);
9209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                    scheduledRunnables.remove(i);
9309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                }
9409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            }
9509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
9609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            Collections.reverse(list);
9709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            for (Runnable r : list) {
9809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                r.run();
9909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki            }
10009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        }
10109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki    }
10209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
10309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki    public void testAll() {
10409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final Context context = mock(Context.class);
10509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final int userId = 11;
10609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final ComponentName cn = ComponentName.unflattenFromString("a.b.c/def");
10709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final Handler handler = new Handler(Looper.getMainLooper());
10809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
10909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final MyConnection conn = new MyConnection("tag", context, handler, userId, cn,
11009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                /* rebindBackoffSeconds= */ 5,
11109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                /* rebindBackoffIncrease= */ 1.5,
11209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                /* rebindMaxBackoffSeconds= */ 11);
11309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
11409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
11509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
11609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
11709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(5000, conn.getNextBackoffMsForTest());
11809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
11909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
12009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        when(context.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class), anyInt(),
12109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                any(Handler.class), any(UserHandle.class)))
12209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                .thenReturn(true);
12309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
12409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Call bind.
12509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.bind();
12609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
12709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
12809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
12909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
13009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
13109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
13209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
13309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(5000, conn.getNextBackoffMsForTest());
13409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
13509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        verify(context).bindServiceAsUser(
13609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                ArgumentMatchers.argThat(intent -> cn.equals(intent.getComponent())),
13709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                eq(conn.getServiceConnectionForTest()),
13809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
13909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                eq(handler), eq(UserHandle.of(userId)));
14009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
14109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // AM responds...
14209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getServiceConnectionForTest().onServiceConnected(cn,
14309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                new IDeviceAdminService.Stub() {});
14409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
14509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
14609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
14709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isConnected());
14809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNotNull(conn.getServiceBinder());
14909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
15009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
15109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(5000, conn.getNextBackoffMsForTest());
15209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
15309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
15409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Now connected.
15509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
15609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Call unbind...
15709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.unbind();
15809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
15909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.shouldBeBoundForTest());
16009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
16109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
16209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
16309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
16409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Caller bind again...
16509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.bind();
16609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
16709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
16809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
16909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
17009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
17109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
17209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
17309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(5000, conn.getNextBackoffMsForTest());
17409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
17509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
17609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Now connected again.
17709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
17809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // The service got killed...
17909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getServiceConnectionForTest().onServiceDisconnected(cn);
18009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
18109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
18209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
18309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
18409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
18509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
18609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
18709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(5000, conn.getNextBackoffMsForTest());
18809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
18909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Connected again...
19009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getServiceConnectionForTest().onServiceConnected(cn,
19109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                new IDeviceAdminService.Stub() {});
19209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
19309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
19409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
19509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isConnected());
19609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNotNull(conn.getServiceBinder());
19709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
19809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
19909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(5000, conn.getNextBackoffMsForTest());
20009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
20109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
20209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Then the binding is "died"...
20309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getServiceConnectionForTest().onBindingDied(cn);
20409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
20509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
20609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
20709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
20809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
20909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isRebindScheduled());
21009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
21109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(7500, conn.getNextBackoffMsForTest());
21209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
21309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(
21409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                Arrays.asList(Pair.create(conn.getBindForBackoffRunnableForTest(),
21509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                        conn.uptimeMillis + 5000)),
21609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                conn.scheduledRunnables);
21709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
21809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // 5000 ms later...
21909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.elapse(5000);
22009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
22109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
22209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
22309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
22409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
22509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
22609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
22709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(7500, conn.getNextBackoffMsForTest());
22809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
22909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Connected.
23009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getServiceConnectionForTest().onServiceConnected(cn,
23109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                new IDeviceAdminService.Stub() {});
23209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
23309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
23409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
23509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isConnected());
23609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNotNull(conn.getServiceBinder());
23709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
23809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
23909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(7500, conn.getNextBackoffMsForTest());
24009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
24109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Then the binding is "died"...
24209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getServiceConnectionForTest().onBindingDied(cn);
24309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
24409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
24509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
24609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
24709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
24809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isRebindScheduled());
24909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
25009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(11000, conn.getNextBackoffMsForTest());
25109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
25209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(
25309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                Arrays.asList(Pair.create(conn.getBindForBackoffRunnableForTest(),
25409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                        conn.uptimeMillis + 7500)),
25509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                conn.scheduledRunnables);
25609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
25709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Later...
25809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.elapse(7500);
25909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
26009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
26109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
26209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
26309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
26409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
26509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
26609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(11000, conn.getNextBackoffMsForTest());
26709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
26809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
26909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Then the binding is "died"...
27009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getServiceConnectionForTest().onBindingDied(cn);
27109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
27209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
27309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
27409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
27509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
27609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isRebindScheduled());
27709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
27809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(11000, conn.getNextBackoffMsForTest());
27909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
28009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(
28109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                Arrays.asList(Pair.create(conn.getBindForBackoffRunnableForTest(),
28209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                    conn.uptimeMillis + 11000)),
28309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                conn.scheduledRunnables);
28409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
28509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Call unbind...
28609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.unbind();
28709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
28809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.shouldBeBoundForTest());
28909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
29009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
29109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
29209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
29309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Call bind again... And now the backoff is reset to 5000.
29409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.bind();
29509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
29609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
29709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
29809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isConnected());
29909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
30009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertNull(conn.getServiceBinder());
30109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
30209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(5000, conn.getNextBackoffMsForTest());
30309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki    }
30409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
30509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki    public void testReconnectFiresAfterUnbind() {
30609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final Context context = mock(Context.class);
30709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final int userId = 11;
30809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final ComponentName cn = ComponentName.unflattenFromString("a.b.c/def");
30909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final Handler handler = new Handler(Looper.getMainLooper());
31009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
31109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        final MyConnection conn = new MyConnection("tag", context, handler, userId, cn,
31209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                /* rebindBackoffSeconds= */ 5,
31309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                /* rebindBackoffIncrease= */ 1.5,
31409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                /* rebindMaxBackoffSeconds= */ 11);
31509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
31609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        when(context.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class), anyInt(),
31709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                any(Handler.class), any(UserHandle.class)))
31809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki                .thenReturn(true);
31909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
32009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Bind.
32109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.bind();
32209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
32309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isBound());
32409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
32509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isRebindScheduled());
32609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
32709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.elapse(1000);
32809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
32909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Service crashes.
33009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getServiceConnectionForTest().onBindingDied(cn);
33109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
33209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
33309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.shouldBeBoundForTest());
33409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertTrue(conn.isRebindScheduled());
33509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
33609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertEquals(7500, conn.getNextBackoffMsForTest());
33709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
33809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Call unbind.
33909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.unbind();
34009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
34109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.shouldBeBoundForTest());
34209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
34309c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Now, at this point, it's possible that the scheduled runnable had already been fired
34409c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // before during the unbind() call, and waiting on mLock.
34509c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // To simulate it, we just call the runnable here.
34609c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        conn.getBindForBackoffRunnableForTest().run();
34709c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki
34809c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        // Should still not be bound.
34909c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.isBound());
35009c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki        assertFalse(conn.shouldBeBoundForTest());
35109c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki    }
35209c529a9bc85bfd0d50b65f447472ad064eac16cMakoto Onuki}
353