1/*
2 * Copyright 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.managedprovisioning.parser;
17
18import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
19import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE;
20import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
21import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
22import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE;
23import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
24import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
25import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
26import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
27import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED;
28import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCALE;
29import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOCAL_TIME;
30import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR;
31import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
32import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_USER_SETUP;
33import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TIME_ZONE;
34import static com.android.managedprovisioning.common.Globals.ACTION_RESUME_PROVISIONING;
35import static com.android.managedprovisioning.model.ProvisioningParams.DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED;
36import static com.android.managedprovisioning.model.ProvisioningParams.DEFAULT_STARTED_BY_TRUSTED_SOURCE;
37import static com.android.managedprovisioning.model.ProvisioningParams.DEFAULT_SKIP_USER_SETUP;
38import static com.android.managedprovisioning.parser.MessageParser.EXTRA_PROVISIONING_ACTION;
39import static com.android.managedprovisioning.parser.MessageParser.EXTRA_PROVISIONING_STARTED_BY_TRUSTED_SOURCE;
40import static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
41import static com.android.managedprovisioning.model.ProvisioningParams.DEFAULT_LOCAL_TIME;
42import static org.mockito.Mockito.doReturn;
43import static org.mockito.Mockito.spy;
44import static org.mockito.Mockito.verify;
45
46import android.accounts.Account;
47import android.app.admin.DevicePolicyManager;
48import android.content.ComponentName;
49import android.content.Context;
50import android.content.Intent;
51import android.nfc.NdefMessage;
52import android.nfc.NdefRecord;
53import android.nfc.NfcAdapter;
54import android.os.PersistableBundle;
55import android.test.AndroidTestCase;
56import android.test.suitebuilder.annotation.SmallTest;
57
58import com.android.managedprovisioning.TestUtils;
59import com.android.managedprovisioning.common.Utils;
60import com.android.managedprovisioning.model.ProvisioningParams;
61
62import org.mockito.Mock;
63import org.mockito.MockitoAnnotations;
64
65import java.io.ByteArrayOutputStream;
66import java.lang.Exception;
67import java.util.Locale;
68import java.util.Properties;
69
70/** Tests {@link MessageParser} */
71@SmallTest
72public class MessageParserTest extends AndroidTestCase {
73    private static final String TEST_PACKAGE_NAME = "com.afwsamples.testdpc";
74    private static final ComponentName TEST_COMPONENT_NAME =
75            ComponentName.unflattenFromString(
76                    "com.afwsamples.testdpc/com.afwsamples.testdpc.DeviceAdminReceiver");
77    private static final long TEST_LOCAL_TIME = 1456939524713L;
78    private static final Locale TEST_LOCALE = Locale.UK;
79    private static final String TEST_TIME_ZONE = "GMT";
80    private static final Integer TEST_MAIN_COLOR = 65280;
81    private static final boolean TEST_SKIP_ENCRYPTION = true;
82    private static final Account TEST_ACCOUNT_TO_MIGRATE =
83            new Account("user@gmail.com", "com.google");
84
85    @Mock
86    private Context mContext;
87
88    private Utils mUtils;
89
90    private MessageParser mMessageParser;
91
92    @Override
93    public void setUp() {
94        // this is necessary for mockito to work
95        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
96
97        MockitoAnnotations.initMocks(this);
98
99        mMessageParser = new MessageParser(mUtils = spy(new Utils()));
100    }
101
102    public void testParseAndRecoverIntent() throws Exception {
103        // GIVEN the device admin app is installed.
104        doReturn(TEST_COMPONENT_NAME)
105                .when(mUtils)
106                .findDeviceAdmin(TEST_PACKAGE_NAME, null, mContext);
107
108        // GIVEN a managed provisioning intent with some extras was being parsed.
109        Intent intent = new Intent(ACTION_PROVISION_MANAGED_PROFILE)
110                .putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, TEST_PACKAGE_NAME)
111                .putExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION, TEST_SKIP_ENCRYPTION)
112                .putExtra(EXTRA_PROVISIONING_MAIN_COLOR, TEST_MAIN_COLOR)
113                .putExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, TEST_ACCOUNT_TO_MIGRATE);
114        ProvisioningParams params = mMessageParser.parse(intent, mContext);
115
116        // WHEN the provisioning data was converted to an intent by getIntentFromProvisioningParams.
117        Intent restoredIntent = mMessageParser.getIntentFromProvisioningParams(params);
118
119        // THEN the intent matches
120        TestUtils.assertIntentEquals(new Intent(ACTION_RESUME_PROVISIONING)
121                        .putExtra(EXTRA_PROVISIONING_ACTION, ACTION_PROVISION_MANAGED_PROFILE)
122                        // Package name is deprecated and replaced by component name only.
123                        .putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, (String) null)
124                        .putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
125                                TEST_COMPONENT_NAME)
126                        .putExtra(EXTRA_PROVISIONING_LOCAL_TIME, DEFAULT_LOCAL_TIME)
127                        .putExtra(EXTRA_PROVISIONING_TIME_ZONE, (String) null)
128                        .putExtra(EXTRA_PROVISIONING_LOCALE, (Locale) null)
129                        .putExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION, TEST_SKIP_ENCRYPTION)
130                        .putExtra(EXTRA_PROVISIONING_SKIP_USER_SETUP, DEFAULT_SKIP_USER_SETUP)
131                        .putExtra(EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED,
132                                DEFAULT_LEAVE_ALL_SYSTEM_APPS_ENABLED)
133                        .putExtra(EXTRA_PROVISIONING_MAIN_COLOR, TEST_MAIN_COLOR)
134                        .putExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, TEST_ACCOUNT_TO_MIGRATE)
135                        .putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, (PersistableBundle) null)
136                        .putExtra(EXTRA_PROVISIONING_STARTED_BY_TRUSTED_SOURCE,
137                                DEFAULT_STARTED_BY_TRUSTED_SOURCE),
138                restoredIntent);
139    }
140
141    public void test_correctParserUsedToParseNfcIntent() throws Exception {
142        // GIVEN a NFC provisioning intent with some supported data.
143        Properties props = new Properties();
144        ByteArrayOutputStream stream = new ByteArrayOutputStream();
145        props.setProperty(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME, TEST_PACKAGE_NAME);
146        props.setProperty(
147                EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME,
148                TEST_COMPONENT_NAME.flattenToString());
149        props.store(stream, "NFC provisioning intent" /* data description */);
150        NdefRecord record = NdefRecord.createMime(
151                DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC,
152                stream.toByteArray());
153        NdefMessage ndfMsg = new NdefMessage(new NdefRecord[]{record});
154
155        Intent intent = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED)
156                .setType(MIME_TYPE_PROVISIONING_NFC)
157                .putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, new NdefMessage[]{ndfMsg});
158
159        // WHEN the mMessageParser.getParser is invoked.
160        ProvisioningDataParser parser = mMessageParser.getParser(intent);
161
162        // THEN the properties parser is returned.
163        assertTrue(parser instanceof PropertiesProvisioningDataParser);
164    }
165
166    public void test_correctParserUsedToParseOtherSupportedProvisioningIntent() throws Exception {
167        // GIVEN the device admin app is installed.
168        doReturn(TEST_COMPONENT_NAME)
169                .when(mUtils)
170                .findDeviceAdmin(null, TEST_COMPONENT_NAME, mContext);
171        // GIVEN a list of supported provisioning actions, except NFC.
172        String[] supportedProvisioningActions = new String[] {
173                ACTION_PROVISION_MANAGED_DEVICE,
174                ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE,
175                ACTION_PROVISION_MANAGED_USER,
176                ACTION_PROVISION_MANAGED_PROFILE,
177                ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE
178        };
179
180        for (String provisioningAction : supportedProvisioningActions) {
181            Intent intent = new Intent(provisioningAction)
182                    .putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, TEST_COMPONENT_NAME);
183
184            // WHEN the mMessageParser.getParser is invoked.
185            ProvisioningDataParser parser = mMessageParser.getParser(intent);
186
187            // THEN the extras parser is returned.
188            assertTrue(parser instanceof ExtrasProvisioningDataParser);
189        }
190    }
191}
192