1 /*
2  * Copyright (C) 2019 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  */
16 
17 package com.android.managedprovisioning.finalization;
18 
19 import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE;
20 import static android.app.admin.DevicePolicyManager.ACTION_PROVISIONING_SUCCESSFUL;
21 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
22 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
23 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
24 
25 import static com.android.managedprovisioning.finalization.SendDpcBroadcastService.EXTRA_PROVISIONING_PARAMS;
26 
27 import static com.google.common.truth.Truth.assertThat;
28 
29 import static org.robolectric.Shadows.shadowOf;
30 
31 import android.annotation.NonNull;
32 import android.app.Application;
33 import android.app.ApplicationPackageManager;
34 import android.content.ComponentName;
35 import android.content.Context;
36 import android.content.Intent;
37 import android.content.pm.PackageManager;
38 import android.content.pm.ResolveInfo;
39 import android.os.PersistableBundle;
40 import android.os.UserManager;
41 
42 import com.android.managedprovisioning.common.ProvisionLogger;
43 import com.android.managedprovisioning.model.ProvisioningParams;
44 
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.robolectric.Robolectric;
49 import org.robolectric.RobolectricTestRunner;
50 import org.robolectric.RuntimeEnvironment;
51 import org.robolectric.android.controller.ServiceController;
52 
53 import java.util.List;
54 import java.util.Objects;
55 
56 /**
57  * Unit tests for {@link SendDpcBroadcastService}.
58  */
59 @RunWith(RobolectricTestRunner.class)
60 public class SendDpcBroadcastServiceTest {
61 
62     private final Context mContext = RuntimeEnvironment.application;
63     private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
64     private final ApplicationPackageManager mPackageManager =
65             (ApplicationPackageManager) mContext.getApplicationContext().getPackageManager();
66     private ServiceController<SendDpcBroadcastService> mController;
67 
68     private static final int USER_HANDLE = 0;
69     private static final int PROFILE_USER_HANDLE = 2;
70 
71     private static final String TEST_MDM_PACKAGE_NAME = "mdm.package.name";
72     private static final String TEST_MDM_ADMIN_RECEIVER = TEST_MDM_PACKAGE_NAME + ".AdminReceiver";
73     private static final ComponentName TEST_MDM_ADMIN = new ComponentName(TEST_MDM_PACKAGE_NAME,
74             TEST_MDM_ADMIN_RECEIVER);
75     private static final PersistableBundle TEST_MDM_EXTRA_BUNDLE = new PersistableBundle();
76     private static final ProvisioningParams PARAMS = ProvisioningParams.Builder.builder()
77             .setProvisioningAction(ACTION_PROVISION_MANAGED_PROFILE)
78             .setDeviceAdminComponentName(TEST_MDM_ADMIN)
79             .setAdminExtrasBundle(TEST_MDM_EXTRA_BUNDLE)
80             .build();
81 
82     private static final String BOOL_KEY = "mybool";
83     private static final boolean BOOL_VALUE = false;
84     private static final String STRING_KEY = "mystring";
85     private static final String STRING_VALUE = "some string";
86     private static final String INT_KEY = "myint";
87     private static final int INT_VALUE = 1234;
88 
89     static {
TEST_MDM_EXTRA_BUNDLE.putBoolean(BOOL_KEY, BOOL_VALUE)90         TEST_MDM_EXTRA_BUNDLE.putBoolean(BOOL_KEY, BOOL_VALUE);
TEST_MDM_EXTRA_BUNDLE.putString(STRING_KEY, STRING_VALUE)91         TEST_MDM_EXTRA_BUNDLE.putString(STRING_KEY, STRING_VALUE);
TEST_MDM_EXTRA_BUNDLE.putInt(INT_KEY, INT_VALUE)92         TEST_MDM_EXTRA_BUNDLE.putInt(INT_KEY, INT_VALUE);
93     }
94 
95     @Before
setUp()96     public void setUp() {
97         final Intent intent =
98                 new Intent(RuntimeEnvironment.application, SendDpcBroadcastService.class)
99                 .putExtra(EXTRA_PROVISIONING_PARAMS, PARAMS);
100         mController = Robolectric.buildService(SendDpcBroadcastService.class, intent);
101 
102         shadowOf(mUserManager).addProfile(
103                 /* userHandle= */ USER_HANDLE,
104                 /* profileUserHandle= */ PROFILE_USER_HANDLE,
105                 /* profileName= */ "profile",
106                 /* profileFlags= */ FLAG_MANAGED_PROFILE);
107     }
108 
109     @Test
onStartCommand_launchesDpc()110     public void onStartCommand_launchesDpc() {
111         shadowOf(mPackageManager)
112                 .addResolveInfoForIntent(createDpcLaunchIntent(), new ResolveInfo());
113 
114         mController.startCommand(/* flags= */ 0, /* startId= */ 0);
115 
116         Intent launchedActivityIntent = shadowOf((Application) mContext).getNextStartedActivity();
117         assertThat(launchedActivityIntent.getPackage()).isEqualTo(TEST_MDM_PACKAGE_NAME);
118         assertThat(launchedActivityIntent.getAction()).isEqualTo(ACTION_PROVISIONING_SUCCESSFUL);
119         assertThat(launchedActivityIntent.getFlags()).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK);
120         assertExtras(launchedActivityIntent);
121     }
122 
123     @Test
onStartCommand_sendsOrderedBroadcast()124     public void onStartCommand_sendsOrderedBroadcast() {
125         shadowOf(mPackageManager)
126                 .addResolveInfoForIntent(createDpcLaunchIntent(), new ResolveInfo());
127 
128         mController.startCommand(/* flags= */ 0, /* startId= */ 0);
129 
130         Intent broadcastIntent = getBroadcastIntentForAction(ACTION_PROFILE_PROVISIONING_COMPLETE);
131         assertThat(broadcastIntent.getComponent()).isEqualTo(TEST_MDM_ADMIN);
132         assertExtras(broadcastIntent);
133     }
134 
getBroadcastIntentForAction(String action)135     private Intent getBroadcastIntentForAction(String action) {
136         List<Intent> broadcastIntents = shadowOf((Application) mContext).getBroadcastIntents();
137         for (Intent intent : broadcastIntents) {
138             if (intent.getAction().equals(action)) {
139                 return intent;
140             }
141         }
142         return null;
143     }
144 
assertExtras(Intent intent)145     private void assertExtras(Intent intent) {
146         final PersistableBundle bundle =
147                 (PersistableBundle) intent.getExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE);
148         assertThat(
149                 bundle.getBoolean(BOOL_KEY)).isEqualTo(TEST_MDM_EXTRA_BUNDLE.getBoolean(BOOL_KEY));
150         assertThat(
151                 bundle.getInt(INT_KEY)).isEqualTo(TEST_MDM_EXTRA_BUNDLE.getInt(INT_KEY));
152         assertThat(
153                 bundle.getInt(STRING_KEY)).isEqualTo(TEST_MDM_EXTRA_BUNDLE.getInt(STRING_KEY));
154     }
155 
createDpcLaunchIntent()156     private Intent createDpcLaunchIntent() {
157         final Intent intent = new Intent(ACTION_PROVISIONING_SUCCESSFUL);
158         final String packageName = PARAMS.inferDeviceAdminPackageName();
159         intent.setPackage(packageName);
160         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
161         intent.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, PARAMS.adminExtrasBundle);
162         return intent;
163     }
164 }
165