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 */
16
17package com.android.server.retaildemo;
18
19import static org.junit.Assert.assertEquals;
20import static org.mockito.Matchers.anyInt;
21import static org.mockito.Matchers.anyString;
22import static org.mockito.Matchers.eq;
23import static org.mockito.Mockito.verify;
24import static org.mockito.Mockito.when;
25
26import android.content.Context;
27import android.content.ContextWrapper;
28import android.content.pm.IPackageInstallObserver2;
29import android.content.pm.IPackageManager;
30import android.content.pm.PackageManager;
31import android.os.FileUtils;
32import android.os.UserHandle;
33import android.provider.Settings;
34import android.support.test.InstrumentationRegistry;
35import android.support.test.filters.SmallTest;
36import android.support.test.runner.AndroidJUnit4;
37import android.test.mock.MockContentResolver;
38
39import com.android.internal.util.test.FakeSettingsProvider;
40
41import org.junit.After;
42import org.junit.Before;
43import org.junit.Test;
44import org.junit.runner.RunWith;
45import org.mockito.ArgumentCaptor;
46import org.mockito.Mock;
47import org.mockito.Mockito;
48import org.mockito.MockitoAnnotations;
49
50import java.io.File;
51import java.util.ArrayList;
52
53@RunWith(AndroidJUnit4.class)
54@SmallTest
55public class PreloadAppsInstallerTest {
56    private static final int TEST_DEMO_USER = 111;
57
58    private Context mContext;
59    private @Mock IPackageManager mIpm;
60    private MockContentResolver mContentResolver;
61    private File mPreloadsAppsDirectory;
62    private String[] mPreloadedApps =
63            new String[] {"test1.apk.preload", "test2.apk.preload", "test3.apk.preload"};
64    private ArrayList<String> mPreloadedAppPaths = new ArrayList<>();
65
66    private PreloadAppsInstaller mInstaller;
67
68    @Before
69    public void setUp() throws Exception {
70        MockitoAnnotations.initMocks(this);
71        mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
72        mContentResolver = new MockContentResolver(mContext);
73        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
74        when(mContext.getContentResolver()).thenReturn(mContentResolver);
75        initializePreloadedApps();
76        Settings.Secure.putStringForUser(mContentResolver,
77                Settings.Secure.DEMO_USER_SETUP_COMPLETE, "0", TEST_DEMO_USER);
78
79        mInstaller = new PreloadAppsInstaller(mContext, mIpm, mPreloadsAppsDirectory);
80    }
81
82    private void initializePreloadedApps() throws Exception {
83        mPreloadsAppsDirectory = new File(InstrumentationRegistry.getContext().getFilesDir(),
84                 "test_preload_apps_dir");
85        mPreloadsAppsDirectory.mkdir();
86        for (String name : mPreloadedApps) {
87            final File f = new File(mPreloadsAppsDirectory, name);
88            f.createNewFile();
89            mPreloadedAppPaths.add(f.getPath());
90        }
91    }
92
93    @After
94    public void tearDown() {
95        if (mPreloadsAppsDirectory != null) {
96            FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
97        }
98    }
99
100    @Test
101    public void testInstallApps() throws Exception {
102        mInstaller.installApps(TEST_DEMO_USER);
103        for (String path : mPreloadedAppPaths) {
104            ArgumentCaptor<IPackageInstallObserver2> observer =
105                    ArgumentCaptor.forClass(IPackageInstallObserver2.class);
106            verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
107                    anyString(), eq(TEST_DEMO_USER));
108            observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
109                    null, null);
110            // Verify that we try to install the package in system user.
111            verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
112                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
113        }
114        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
115                "1",
116                Settings.Secure.getStringForUser(mContentResolver,
117                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
118    }
119
120    @Test
121    public void testInstallApps_noPreloads() throws Exception {
122        // Delete all files in preloaded apps directory - no preloaded apps
123        FileUtils.deleteContents(mPreloadsAppsDirectory);
124        mInstaller.installApps(TEST_DEMO_USER);
125        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
126                "1",
127                Settings.Secure.getStringForUser(mContentResolver,
128                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
129    }
130
131    @Test
132    public void testInstallApps_installationFails() throws Exception {
133        mInstaller.installApps(TEST_DEMO_USER);
134        for (int i = 0; i < mPreloadedAppPaths.size(); ++i) {
135            ArgumentCaptor<IPackageInstallObserver2> observer =
136                    ArgumentCaptor.forClass(IPackageInstallObserver2.class);
137            final String path = mPreloadedAppPaths.get(i);
138            verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
139                    anyString(), eq(TEST_DEMO_USER));
140            if (i == 0) {
141                observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_FAILED_DEXOPT,
142                        null, null);
143                continue;
144            }
145            observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
146                    null, null);
147            // Verify that we try to install the package in system user.
148            verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
149                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
150        }
151        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
152                "1",
153                Settings.Secure.getStringForUser(mContentResolver,
154                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
155    }
156}
157