1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.devicepolicy;
17
18import static com.android.server.devicepolicy.NetworkLoggingHandler.LOG_NETWORK_EVENT_MSG;
19
20import static org.mockito.ArgumentMatchers.any;
21import static org.mockito.Mockito.doNothing;
22import static org.mockito.Mockito.spy;
23import static org.mockito.Mockito.verify;
24
25import android.app.admin.ConnectEvent;
26import android.app.admin.DeviceAdminReceiver;
27import android.app.admin.DevicePolicyManagerInternal;
28import android.app.admin.DnsEvent;
29import android.app.admin.NetworkEvent;
30import android.content.Intent;
31import android.os.Bundle;
32import android.os.Message;
33import android.os.Parcel;
34import android.os.SystemClock;
35import android.os.UserHandle;
36import android.os.test.TestLooper;
37import android.test.suitebuilder.annotation.SmallTest;
38
39import com.android.server.LocalServices;
40import com.android.server.SystemService;
41
42import org.mockito.ArgumentCaptor;
43
44import java.util.List;
45
46@SmallTest
47public class NetworkEventTest extends DpmTestBase {
48    private static final int MAX_EVENTS_PER_BATCH = 1200;
49
50    private DpmMockContext mSpiedDpmMockContext;
51    private DevicePolicyManagerServiceTestable mDpmTestable;
52
53    @Override
54    protected void setUp() throws Exception {
55        super.setUp();
56        mSpiedDpmMockContext = spy(mMockContext);
57        mSpiedDpmMockContext.callerPermissions.add(
58                android.Manifest.permission.MANAGE_DEVICE_ADMINS);
59        doNothing().when(mSpiedDpmMockContext).sendBroadcastAsUser(any(Intent.class),
60                any(UserHandle.class));
61        LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
62        mDpmTestable = new DevicePolicyManagerServiceTestable(getServices(), mSpiedDpmMockContext);
63        setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
64        mDpmTestable.setActiveAdmin(admin1, true, DpmMockContext.CALLER_USER_HANDLE);
65    }
66
67    public void testNetworkEventId_monotonicallyIncreasing() throws Exception {
68        // GIVEN the handler has not processed any events.
69        long startingId = 0;
70
71        // WHEN the handler has processed the events.
72        List<NetworkEvent> events = fillHandlerWithFullBatchOfEvents(startingId);
73
74        // THEN the events are in a batch.
75        assertTrue("Batch not at the returned token.",
76                events != null && events.size() == MAX_EVENTS_PER_BATCH);
77        // THEN event ids are monotonically increasing.
78        long expectedId = startingId;
79        for (int i = 0; i < MAX_EVENTS_PER_BATCH; i++) {
80            assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
81                    events.get(i).getId());
82            expectedId++;
83        }
84    }
85
86    public void testNetworkEventId_wrapsAround() throws Exception {
87        // GIVEN the handler has almost processed Long.MAX_VALUE events.
88        int gap = 5;
89        long startingId = Long.MAX_VALUE - gap;
90
91        // WHEN the handler has processed the events.
92        List<NetworkEvent> events = fillHandlerWithFullBatchOfEvents(startingId);
93
94        // THEN the events are in a batch.
95        assertTrue("Batch not at the returned token.",
96                events != null && events.size() == MAX_EVENTS_PER_BATCH);
97        // THEN event ids are monotonically increasing.
98        long expectedId = startingId;
99        for (int i = 0; i < gap; i++) {
100            assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
101                    events.get(i).getId());
102            expectedId++;
103        }
104        // THEN event ids are reset when the id reaches the maximum possible value.
105        assertEquals("Event was not assigned the maximum id value.", Long.MAX_VALUE,
106                events.get(gap).getId());
107        assertEquals("Event id was not reset.", 0, events.get(gap + 1).getId());
108        // THEN event ids are monotonically increasing.
109        expectedId = 0;
110        for (int i = gap + 1; i < MAX_EVENTS_PER_BATCH; i++) {
111            assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
112                    events.get(i).getId());
113            expectedId++;
114        }
115    }
116
117    private List<NetworkEvent> fillHandlerWithFullBatchOfEvents(long startingId) throws Exception {
118        // GIVEN a handler with events
119        NetworkLoggingHandler handler = new NetworkLoggingHandler(new TestLooper().getLooper(),
120                mDpmTestable, startingId);
121        // GIVEN network events are sent to the handler.
122        for (int i = 0; i < MAX_EVENTS_PER_BATCH; i++) {
123            ConnectEvent event = new ConnectEvent("some_ip_address", 800, "com.google.foo",
124                    SystemClock.currentThreadTimeMillis());
125            Message msg = new Message();
126            msg.what = LOG_NETWORK_EVENT_MSG;
127            Bundle bundle = new Bundle();
128            bundle.putParcelable(NetworkLoggingHandler.NETWORK_EVENT_KEY, event);
129            msg.setData(bundle);
130            handler.handleMessage(msg);
131        }
132
133        // WHEN the handler processes the events.
134        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
135        verify(mSpiedDpmMockContext).sendBroadcastAsUser(intentCaptor.capture(),
136                any(UserHandle.class));
137        assertEquals(intentCaptor.getValue().getAction(),
138                DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE);
139        long token = intentCaptor.getValue().getExtras().getLong(
140                DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, 0);
141        return handler.retrieveFullLogBatch(token);
142    }
143
144    /**
145     * Test parceling and unparceling of a ConnectEvent.
146     */
147    public void testConnectEventParceling() {
148        ConnectEvent event = new ConnectEvent("127.0.0.1", 80, "com.android.whateverdude", 100000);
149        event.setId(5L);
150        Parcel p = Parcel.obtain();
151        p.writeParcelable(event, 0);
152        p.setDataPosition(0);
153        ConnectEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
154        p.recycle();
155        assertEquals(event.getInetAddress(), unparceledEvent.getInetAddress());
156        assertEquals(event.getPort(), unparceledEvent.getPort());
157        assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
158        assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
159        assertEquals(event.getId(), unparceledEvent.getId());
160    }
161
162    /**
163     * Test parceling and unparceling of a DnsEvent.
164     */
165    public void testDnsEventParceling() {
166        DnsEvent event = new DnsEvent("d.android.com", new String[]{"192.168.0.1", "127.0.0.1"}, 2,
167                "com.android.whateverdude", 100000);
168        event.setId(5L);
169        Parcel p = Parcel.obtain();
170        p.writeParcelable(event, 0);
171        p.setDataPosition(0);
172        DnsEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
173        p.recycle();
174        assertEquals(event.getHostname(), unparceledEvent.getHostname());
175        assertEquals(event.getInetAddresses().get(0), unparceledEvent.getInetAddresses().get(0));
176        assertEquals(event.getInetAddresses().get(1), unparceledEvent.getInetAddresses().get(1));
177        assertEquals(event.getTotalResolvedAddressCount(),
178                unparceledEvent.getTotalResolvedAddressCount());
179        assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
180        assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
181        assertEquals(event.getId(), unparceledEvent.getId());
182    }
183}
184