1 /* 2 * Copyright (C) 2014 The Android Open Sour * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package com.android.cts.launchertests.support; 17 18 import android.app.Service; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.pm.LauncherApps; 22 import android.content.pm.PackageManager.NameNotFoundException; 23 import android.os.Bundle; 24 import android.os.Handler; 25 import android.os.HandlerThread; 26 import android.os.IBinder; 27 import android.os.Message; 28 import android.os.Messenger; 29 import android.os.RemoteException; 30 import android.os.UserHandle; 31 import android.util.Log; 32 import android.util.Pair; 33 34 import java.util.ArrayList; 35 import java.util.concurrent.BlockingQueue; 36 import java.util.concurrent.LinkedBlockingQueue; 37 import java.util.concurrent.TimeUnit; 38 import java.util.List; 39 40 /** 41 * Service that registers for LauncherApps callbacks. 42 * 43 * Registering in a service and different process so that 44 * device side code can launch it before running client 45 * side test code. 46 */ 47 public class LauncherCallbackTestsService extends Service { 48 49 public static final String USER_EXTRA = "user_extra"; 50 public static final String PACKAGE_EXTRA = "package_extra"; 51 52 public static final int MSG_RESULT = 0; 53 public static final int MSG_CHECK_PACKAGE_ADDED = 1; 54 public static final int MSG_CHECK_PACKAGE_REMOVED = 2; 55 public static final int MSG_CHECK_PACKAGE_CHANGED = 3; 56 public static final int MSG_CHECK_NO_PACKAGE_ADDED = 4; 57 58 public static final int RESULT_PASS = 1; 59 public static final int RESULT_FAIL = 2; 60 61 private static final String TAG = "LauncherCallbackTests"; 62 63 private static BlockingQueue<Pair<String, UserHandle>> mPackagesAdded 64 = new LinkedBlockingQueue(); 65 private static BlockingQueue<Pair<String, UserHandle>> mPackagesRemoved 66 = new LinkedBlockingQueue(); 67 private static BlockingQueue<Pair<String, UserHandle>> mPackagesChanged 68 = new LinkedBlockingQueue(); 69 70 private TestCallback mCallback; 71 private Object mCallbackLock = new Object(); 72 private final Messenger mMessenger = new Messenger(new CheckHandler()); 73 private final HandlerThread mCallbackThread = new HandlerThread("callback"); 74 LauncherCallbackTestsService()75 public LauncherCallbackTestsService() { 76 mCallbackThread.start(); 77 } 78 79 class CheckHandler extends Handler { 80 @Override handleMessage(Message msg)81 public void handleMessage(Message msg) { 82 Bundle params = null; 83 if (msg.obj instanceof Bundle) { 84 params = (Bundle) (msg.obj); 85 } 86 try { 87 switch (msg.what) { 88 case MSG_CHECK_PACKAGE_ADDED: { 89 Log.i(TAG, "MSG_CHECK_PACKAGE_ADDED"); 90 boolean exists = eventExists(params, mPackagesAdded); 91 teardown(); 92 msg.replyTo.send(Message.obtain(null, MSG_RESULT, 93 exists ? RESULT_PASS : RESULT_FAIL, 0)); 94 break; 95 } 96 case MSG_CHECK_PACKAGE_REMOVED: { 97 Log.i(TAG, "MSG_CHECK_PACKAGE_REMOVED"); 98 boolean exists = eventExists(params, mPackagesRemoved); 99 teardown(); 100 msg.replyTo.send(Message.obtain(null, MSG_RESULT, 101 exists ? RESULT_PASS : RESULT_FAIL, 0)); 102 break; 103 } 104 case MSG_CHECK_PACKAGE_CHANGED: { 105 Log.i(TAG, "MSG_CHECK_PACKAGE_CHANGED"); 106 boolean exists = eventExists(params, mPackagesChanged); 107 teardown(); 108 msg.replyTo.send(Message.obtain(null, MSG_RESULT, 109 exists ? RESULT_PASS : RESULT_FAIL, 0)); 110 break; 111 } 112 case MSG_CHECK_NO_PACKAGE_ADDED: { 113 Log.i(TAG, "MSG_CHECK_NO_PACKAGE_ADDED"); 114 boolean exists = eventExists(params, mPackagesAdded); 115 teardown(); 116 msg.replyTo.send(Message.obtain(null, MSG_RESULT, 117 exists ? RESULT_FAIL : RESULT_PASS, 0)); 118 break; 119 } 120 default: 121 super.handleMessage(msg); 122 } 123 } catch (RemoteException e) { 124 Log.e(TAG, "Failed to report test status"); 125 } 126 } 127 } 128 129 @Override onStartCommand(Intent intent, int flags, int startId)130 public int onStartCommand(Intent intent, int flags, int startId) { 131 if (intent == null) { 132 return START_NOT_STICKY; 133 } 134 if ("com.android.cts.launchertests.support.REGISTER_CALLBACK".equals(intent.getAction())) { 135 setup(); 136 } 137 return START_STICKY; 138 } 139 setup()140 private void setup() { 141 LauncherApps launcherApps = (LauncherApps) getSystemService( 142 Context.LAUNCHER_APPS_SERVICE); 143 synchronized (mCallbackLock) { 144 if (mCallback != null) { 145 launcherApps.unregisterCallback(mCallback); 146 } 147 mPackagesAdded.clear(); 148 mPackagesRemoved.clear(); 149 mPackagesChanged.clear(); 150 mCallback = new TestCallback(); 151 launcherApps.registerCallback(mCallback, new Handler(mCallbackThread.getLooper())); 152 Log.i(TAG, "started listening for events"); 153 } 154 } 155 teardown()156 private void teardown() { 157 LauncherApps launcherApps = (LauncherApps) getSystemService( 158 Context.LAUNCHER_APPS_SERVICE); 159 synchronized (mCallbackLock) { 160 if (mCallback != null) { 161 launcherApps.unregisterCallback(mCallback); 162 Log.i(TAG, "stopped listening for events"); 163 mCallback = null; 164 } 165 mPackagesAdded.clear(); 166 mPackagesRemoved.clear(); 167 mPackagesChanged.clear(); 168 } 169 } 170 eventExists(Bundle params, BlockingQueue<Pair<String, UserHandle>> events)171 private boolean eventExists(Bundle params, BlockingQueue<Pair<String, UserHandle>> events) { 172 UserHandle user = params.getParcelable(USER_EXTRA); 173 String packageName = params.getString(PACKAGE_EXTRA); 174 Log.i(TAG, "checking for " + packageName + " " + user); 175 try { 176 Pair<String, UserHandle> event = events.poll(60, TimeUnit.SECONDS); 177 while (event != null) { 178 if (event.first.equals(packageName) && event.second.equals(user)) { 179 Log.i(TAG, "Event exists " + packageName + " for user " + user); 180 return true; 181 } 182 event = events.poll(20, TimeUnit.SECONDS); 183 } 184 } catch (InterruptedException e) { 185 Log.e(TAG, "Failed checking for event", e); 186 } 187 return false; 188 } 189 190 @Override onBind(Intent intent)191 public IBinder onBind(Intent intent) { 192 return mMessenger.getBinder(); 193 } 194 195 private class TestCallback extends LauncherApps.Callback { onPackageRemoved(String packageName, UserHandle user)196 public void onPackageRemoved(String packageName, UserHandle user) { 197 Log.i(TAG, "package removed event " + packageName + " " + user); 198 try { 199 mPackagesRemoved.put(new Pair(packageName, user)); 200 } catch (InterruptedException e) { 201 Log.e(TAG, "Failed saving event", e); 202 } 203 } 204 onPackageAdded(String packageName, UserHandle user)205 public void onPackageAdded(String packageName, UserHandle user) { 206 Log.i(TAG, "package added event " + packageName + " " + user); 207 try { 208 mPackagesAdded.put(new Pair(packageName, user)); 209 } catch (InterruptedException e) { 210 Log.e(TAG, "Failed saving event", e); 211 } 212 } 213 onPackageChanged(String packageName, UserHandle user)214 public void onPackageChanged(String packageName, UserHandle user) { 215 Log.i(TAG, "package changed event " + packageName + " " + user); 216 try { 217 mPackagesChanged.put(new Pair(packageName, user)); 218 } catch (InterruptedException e) { 219 Log.e(TAG, "Failed saving event", e); 220 } 221 } 222 onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing)223 public void onPackagesAvailable(String[] packageNames, UserHandle user, 224 boolean replacing) { 225 } 226 onPackagesUnavailable(String[] packageNames, UserHandle user, boolean replacing)227 public void onPackagesUnavailable(String[] packageNames, UserHandle user, 228 boolean replacing) { 229 } 230 } 231 } 232