Kenny Guy | da65244 | 2015-01-26 14:49:13 +0000 | [diff] [blame^] | 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.test.InstrumentationTestCase; |
| 42 | import android.test.InstrumentationTestRunner; |
| 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 InstrumentationTestCase { |
| 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_CALLBACK = 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 InstrumentationTestRunner mInstrumentation; |
| 73 | private Messenger mService; |
| 74 | private Connection mConnection; |
| 75 | private Result mResult; |
| 76 | private Messenger mResultMessenger; |
| 77 | |
| 78 | @Override |
| 79 | protected void setUp() throws Exception { |
| 80 | super.setUp(); |
| 81 | mInstrumentation = (InstrumentationTestRunner) getInstrumentation(); |
| 82 | Bundle arguments = mInstrumentation.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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | } |
| 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 | |
| 142 | public void testNoCallbackForUser() throws Throwable { |
| 143 | int result = sendMessageToCallbacksService(MSG_CHECK_NO_CALLBACK, |
| 144 | mUser, SIMPLE_APP_PACKAGE); |
| 145 | assertEquals(RESULT_PASS, result); |
| 146 | } |
| 147 | |
| 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 | |
| 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 | |
| 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 | |
| 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 |
| 199 | public void onServiceConnected(ComponentName className, IBinder service) { |
| 200 | mService = new Messenger(service); |
| 201 | mSemaphore.release(); |
| 202 | } |
| 203 | |
| 204 | @Override |
| 205 | public void onServiceDisconnected(ComponentName className) { |
| 206 | mService = null; |
| 207 | } |
| 208 | |
| 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 | |
| 225 | public Result(Looper looper) { |
| 226 | super(looper); |
| 227 | } |
| 228 | |
| 229 | @Override |
| 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 | |
| 239 | public int waitForResult() { |
| 240 | try { |
| 241 | if (mSemaphore.tryAcquire(5, 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 |
| 257 | public void onReceive(Context context, Intent intent) { |
| 258 | if (intent.getAction().equals(ACTIVITY_LAUNCHED_ACTION)) { |
| 259 | mSemaphore.release(); |
| 260 | } |
| 261 | } |
| 262 | |
| 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 | |
| 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 | } |