1 /*
2  * Copyright (C) 2014 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 package com.android.cts.launchertests;
17 
18 import android.app.admin.DeviceAdminReceiver;
19 import android.app.admin.DevicePolicyManager;
20 import android.app.Activity;
21 import android.app.Instrumentation;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.pm.LauncherActivityInfo;
28 import android.content.pm.LauncherApps;
29 import android.content.ServiceConnection;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.IBinder;
33 import android.os.Looper;
34 import android.os.Message;
35 import android.os.Messenger;
36 import android.os.Parcel;
37 import android.os.RemoteException;
38 import android.os.ResultReceiver;
39 import android.os.UserHandle;
40 import android.os.UserManager;
41 import android.support.test.InstrumentationRegistry;
42 import android.test.AndroidTestCase;
43 import android.util.Pair;
44 
45 import java.util.concurrent.Semaphore;
46 import java.util.concurrent.TimeUnit;
47 import java.util.List;
48 
49 /**
50  * Tests for LauncherApps service
51  */
52 public class LauncherAppsTests extends AndroidTestCase {
53 
54     public static final String SIMPLE_APP_PACKAGE = "com.android.cts.launcherapps.simpleapp";
55 
56     public static final String USER_EXTRA = "user_extra";
57     public static final String PACKAGE_EXTRA = "package_extra";
58     public static final String REPLY_EXTRA = "reply_extra";
59 
60     public static final int MSG_RESULT = 0;
61     public static final int MSG_CHECK_PACKAGE_ADDED = 1;
62     public static final int MSG_CHECK_PACKAGE_REMOVED = 2;
63     public static final int MSG_CHECK_PACKAGE_CHANGED = 3;
64     public static final int MSG_CHECK_NO_PACKAGE_ADDED = 4;
65 
66     public static final int RESULT_PASS = 1;
67     public static final int RESULT_FAIL = 2;
68     public static final int RESULT_TIMEOUT = 3;
69 
70     private LauncherApps mLauncherApps;
71     private UserHandle mUser;
72     private Instrumentation mInstrumentation;
73     private Messenger mService;
74     private Connection mConnection;
75     private Result mResult;
76     private Messenger mResultMessenger;
77 
78     @Override
setUp()79     protected void setUp() throws Exception {
80         super.setUp();
81         mInstrumentation = InstrumentationRegistry.getInstrumentation();
82         Bundle arguments = InstrumentationRegistry.getArguments();
83         UserManager userManager = (UserManager) mInstrumentation.getContext().getSystemService(
84                 Context.USER_SERVICE);
85         mUser = getUserHandleArgument(userManager, "testUser", arguments);
86         mLauncherApps = (LauncherApps) mInstrumentation.getContext().getSystemService(
87                 Context.LAUNCHER_APPS_SERVICE);
88 
89         final Intent intent = new Intent();
90         intent.setComponent(new ComponentName("com.android.cts.launchertests.support",
91                         "com.android.cts.launchertests.support.LauncherCallbackTestsService"));
92 
93         mConnection = new Connection();
94         mInstrumentation.getContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
95         mConnection.waitForService();
96         mResult = new Result(Looper.getMainLooper());
97         mResultMessenger = new Messenger(mResult);
98     }
99 
testGetActivitiesForUserFails()100     public void testGetActivitiesForUserFails() throws Exception {
101         try {
102             List<LauncherActivityInfo> activities =
103                     mLauncherApps.getActivityList(null, mUser);
104             fail("getActivities for non-profile user failed to throw exception");
105         } catch (SecurityException e) {
106             // Expected.
107         }
108     }
109 
testSimpleAppInstalledForUser()110     public void testSimpleAppInstalledForUser() throws Exception {
111         List<LauncherActivityInfo> activities =
112                 mLauncherApps.getActivityList(null, mUser);
113         // Check simple app is there.
114         boolean foundSimpleApp = false;
115         for (LauncherActivityInfo activity : activities) {
116             if (activity.getComponentName().getPackageName().equals(
117                     SIMPLE_APP_PACKAGE)) {
118                 foundSimpleApp = true;
119             }
120             assertTrue(activity.getUser().equals(mUser));
121         }
122         assertTrue(foundSimpleApp);
123     }
124 
testPackageAddedCallbackForUser()125     public void testPackageAddedCallbackForUser() throws Throwable {
126         int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_ADDED,
127                 mUser, SIMPLE_APP_PACKAGE);
128         assertEquals(RESULT_PASS, result);
129     }
130 
testPackageRemovedCallbackForUser()131     public void testPackageRemovedCallbackForUser() throws Throwable {
132         int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_REMOVED,
133                 mUser, SIMPLE_APP_PACKAGE);
134         assertEquals(RESULT_PASS, result);
135     }
testPackageChangedCallbackForUser()136     public void testPackageChangedCallbackForUser() throws Throwable {
137         int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_CHANGED,
138                 mUser, SIMPLE_APP_PACKAGE);
139         assertEquals(RESULT_PASS, result);
140     }
141 
testNoPackageAddedCallbackForUser()142     public void testNoPackageAddedCallbackForUser() throws Throwable {
143         int result = sendMessageToCallbacksService(MSG_CHECK_NO_PACKAGE_ADDED,
144                 mUser, SIMPLE_APP_PACKAGE);
145         assertEquals(RESULT_PASS, result);
146     }
147 
testLaunchNonExportActivityFails()148     public void testLaunchNonExportActivityFails() throws Exception {
149         try {
150             mLauncherApps.startMainActivity(new ComponentName(
151                     SIMPLE_APP_PACKAGE,
152                     SIMPLE_APP_PACKAGE + ".NonExportedActivity"),
153                     mUser, null, null);
154             fail("starting non-exported activity failed to throw exception");
155         } catch (SecurityException e) {
156             // Expected.
157         }
158     }
159 
testLaunchNonExportLauncherFails()160     public void testLaunchNonExportLauncherFails() throws Exception {
161         try {
162             mLauncherApps.startMainActivity(new ComponentName(
163                     SIMPLE_APP_PACKAGE,
164                     SIMPLE_APP_PACKAGE + ".NonLauncherActivity"),
165                     mUser, null, null);
166             fail("starting non-launcher activity failed to throw exception");
167         } catch (SecurityException e) {
168             // Expected.
169         }
170     }
171 
testLaunchMainActivity()172     public void testLaunchMainActivity() throws Exception {
173         ActivityLaunchedReceiver receiver = new ActivityLaunchedReceiver();
174         IntentFilter filter = new IntentFilter();
175         filter.addAction(ActivityLaunchedReceiver.ACTIVITY_LAUNCHED_ACTION);
176         mInstrumentation.getContext().registerReceiver(receiver, filter);
177         mLauncherApps.startMainActivity(new ComponentName(
178                 SIMPLE_APP_PACKAGE,
179                 SIMPLE_APP_PACKAGE + ".SimpleActivity"),
180                 mUser, null, null);
181         assertEquals(RESULT_PASS, receiver.waitForActivity());
182         mInstrumentation.getContext().unregisterReceiver(receiver);
183     }
184 
getUserHandleArgument(UserManager userManager, String key, Bundle arguments)185     private UserHandle getUserHandleArgument(UserManager userManager, String key,
186             Bundle arguments) throws Exception {
187         String serial = arguments.getString(key);
188         if (serial == null) {
189             return null;
190         }
191         int serialNo = Integer.parseInt(serial);
192         return userManager.getUserForSerialNumber(serialNo);
193     }
194 
195     private class Connection implements ServiceConnection {
196         private final Semaphore mSemaphore = new Semaphore(0);
197 
198         @Override
onServiceConnected(ComponentName className, IBinder service)199         public void onServiceConnected(ComponentName className, IBinder service) {
200             mService = new Messenger(service);
201             mSemaphore.release();
202         }
203 
204         @Override
onServiceDisconnected(ComponentName className)205         public void onServiceDisconnected(ComponentName className) {
206             mService = null;
207         }
208 
waitForService()209         public void waitForService() {
210             try {
211                 if (mSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
212                     return;
213                 }
214             } catch (InterruptedException e) {
215             }
216             fail("failed to connec to service");
217         }
218     };
219 
220     private static class Result extends Handler {
221 
222         private final Semaphore mSemaphore = new Semaphore(0);
223         public int result = 0;
224 
Result(Looper looper)225         public Result(Looper looper) {
226             super(looper);
227         }
228 
229         @Override
handleMessage(Message msg)230         public void handleMessage(Message msg) {
231             if (msg.what == MSG_RESULT) {
232                 result = msg.arg1;
233                 mSemaphore.release();
234             } else {
235                 super.handleMessage(msg);
236             }
237         }
238 
waitForResult()239         public int waitForResult() {
240             try {
241                 if (mSemaphore.tryAcquire(120, TimeUnit.SECONDS)) {
242                      return result;
243                 }
244             } catch (InterruptedException e) {
245             }
246             return RESULT_TIMEOUT;
247         }
248     }
249 
250     public class ActivityLaunchedReceiver extends BroadcastReceiver {
251         public static final String ACTIVITY_LAUNCHED_ACTION =
252                 "com.android.cts.launchertests.LauncherAppsTests.LAUNCHED_ACTION";
253 
254         private final Semaphore mSemaphore = new Semaphore(0);
255 
256         @Override
onReceive(Context context, Intent intent)257         public void onReceive(Context context, Intent intent) {
258             if (intent.getAction().equals(ACTIVITY_LAUNCHED_ACTION)) {
259                 mSemaphore.release();
260             }
261         }
262 
waitForActivity()263         public int waitForActivity() {
264             try {
265                 if (mSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
266                     return RESULT_PASS;
267                 }
268             } catch (InterruptedException e) {
269             }
270             return RESULT_TIMEOUT;
271         }
272     }
273 
sendMessageToCallbacksService(int msg, UserHandle user, String packageName)274     private int sendMessageToCallbacksService(int msg, UserHandle user, String packageName)
275             throws Throwable {
276         Bundle params = new Bundle();
277         params.putParcelable(USER_EXTRA, user);
278         params.putString(PACKAGE_EXTRA, packageName);
279 
280         Message message = Message.obtain(null, msg, params);
281         message.replyTo = mResultMessenger;
282 
283         mService.send(message);
284 
285         return mResult.waitForResult();
286     }
287 }
288