• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 android.app.stubs;
18 
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.app.ForegroundServiceStartNotAllowedException;
22 import android.app.IActivityManager;
23 import android.app.PendingIntent;
24 import android.content.BroadcastReceiver;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.ServiceConnection;
29 import android.content.pm.PackageManager;
30 import android.os.Bundle;
31 import android.os.IBinder;
32 import android.os.Parcel;
33 import android.os.RemoteException;
34 import android.text.TextUtils;
35 import android.util.ArrayMap;
36 import android.util.Log;
37 
38 import java.util.concurrent.TimeUnit;
39 
40 public class CommandReceiver extends BroadcastReceiver {
41 
42     private static final String TAG = "CommandReceiver";
43 
44     // Requires flags and targetPackage
45     public static final int COMMAND_BIND_SERVICE = 1;
46     // Requires targetPackage
47     public static final int COMMAND_UNBIND_SERVICE = 2;
48     public static final int COMMAND_START_FOREGROUND_SERVICE = 3;
49     public static final int COMMAND_STOP_FOREGROUND_SERVICE = 4;
50     public static final int COMMAND_START_FOREGROUND_SERVICE_LOCATION = 5;
51     public static final int COMMAND_STOP_FOREGROUND_SERVICE_LOCATION = 6;
52     public static final int COMMAND_START_ALERT_SERVICE = 7;
53     public static final int COMMAND_STOP_ALERT_SERVICE = 8;
54     public static final int COMMAND_SELF_INDUCED_ANR = 9;
55     public static final int COMMAND_START_ACTIVITY = 10;
56     public static final int COMMAND_STOP_ACTIVITY = 11;
57     public static final int COMMAND_CREATE_FGSL_PENDING_INTENT = 12;
58     public static final int COMMAND_SEND_FGSL_PENDING_INTENT = 13;
59     public static final int COMMAND_BIND_FOREGROUND_SERVICE = 14;
60     public static final int COMMAND_START_CHILD_PROCESS = 15;
61     public static final int COMMAND_STOP_CHILD_PROCESS = 16;
62     public static final int COMMAND_WAIT_FOR_CHILD_PROCESS_GONE = 17;
63     public static final int COMMAND_START_SERVICE = 18;
64     public static final int COMMAND_STOP_SERVICE = 19;
65     public static final int COMMAND_START_FOREGROUND_SERVICE_STICKY = 20;
66     public static final int COMMAND_STOP_FOREGROUND_SERVICE_STICKY = 21;
67     public static final int COMMAND_EMPTY = 22;
68     public static final int COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME = 23;
69 
70     public static final int RESULT_CHILD_PROCESS_STARTED = IBinder.FIRST_CALL_TRANSACTION;
71     public static final int RESULT_CHILD_PROCESS_STOPPED = IBinder.FIRST_CALL_TRANSACTION + 1;
72     public static final int RESULT_CHILD_PROCESS_GONE = IBinder.FIRST_CALL_TRANSACTION + 2;
73 
74     public static final String EXTRA_COMMAND = "android.app.stubs.extra.COMMAND";
75     public static final String EXTRA_TARGET_PACKAGE = "android.app.stubs.extra.TARGET_PACKAGE";
76     public static final String EXTRA_FLAGS = "android.app.stubs.extra.FLAGS";
77     public static final String EXTRA_CALLBACK = "android.app.stubs.extra.callback";
78     public static final String EXTRA_CHILD_CMDLINE = "android.app.stubs.extra.child_cmdline";
79     public static final String EXTRA_TIMEOUT = "android.app.stubs.extra.child_cmdline";
80     public static final String EXTRA_MESSENGER = "android.app.stubs.extra.EXTRA_MESSENGER";
81 
82     public static final String SERVICE_NAME = "android.app.stubs.LocalService";
83     public static final String FG_SERVICE_NAME = "android.app.stubs.LocalForegroundService";
84     public static final String FG_LOCATION_SERVICE_NAME =
85             "android.app.stubs.LocalForegroundServiceLocation";
86     public static final String FG_STICKY_SERVICE_NAME =
87             "android.app.stubs.LocalForegroundServiceSticky";
88 
89     public static final String ACTIVITY_NAME = "android.app.stubs.SimpleActivity";
90 
91     private static ArrayMap<String,ServiceConnection> sServiceMap = new ArrayMap<>();
92 
93     // Map a packageName to a Intent that starts an Activity.
94     private static ArrayMap<String, Intent> sActivityIntent = new ArrayMap<>();
95 
96     // Map a packageName to a PendingIntent.
97     private static ArrayMap<String, PendingIntent> sPendingIntent = new ArrayMap<>();
98 
99     /** The child process, started via {@link #COMMAND_START_CHILD_PROCESS} */
100     private static Process sChildProcess;
101 
102     /**
103      * Handle the different types of binding/unbinding requests.
104      * @param context The Context in which the receiver is running.
105      * @param intent The Intent being received.
106      */
107     @Override
onReceive(Context context, Intent intent)108     public void onReceive(Context context, Intent intent) {
109         // Use the application context as the receiver context could be restricted.
110         context = context.getApplicationContext();
111         int command = intent.getIntExtra(EXTRA_COMMAND, -1);
112         Log.d(TAG + "_" + context.getPackageName(), "Got command " + command + ", intent="
113                 + intent);
114         switch (command) {
115             case COMMAND_BIND_SERVICE:
116                 doBindService(context, intent, SERVICE_NAME);
117                 break;
118             case COMMAND_UNBIND_SERVICE:
119                 doUnbindService(context, intent);
120                 break;
121             case COMMAND_START_FOREGROUND_SERVICE:
122                 doStartForegroundService(context, intent);
123                 break;
124             case COMMAND_START_SERVICE:
125                 doStartService(context, intent);
126                 break;
127             case COMMAND_STOP_FOREGROUND_SERVICE:
128             case COMMAND_STOP_SERVICE:
129                 doStopService(context, intent, FG_SERVICE_NAME);
130                 break;
131             case COMMAND_START_FOREGROUND_SERVICE_LOCATION:
132                 doStartForegroundServiceWithType(context, intent);
133                 break;
134             case COMMAND_STOP_FOREGROUND_SERVICE_LOCATION:
135                 doStopService(context, intent, FG_LOCATION_SERVICE_NAME);
136                 break;
137             case COMMAND_START_FOREGROUND_SERVICE_STICKY:
138                 doStartForegroundServiceSticky(context, intent);
139                 break;
140             case COMMAND_STOP_FOREGROUND_SERVICE_STICKY:
141                 doStopService(context, intent, FG_STICKY_SERVICE_NAME);
142                 break;
143             case COMMAND_START_ALERT_SERVICE:
144                 doStartAlertService(context);
145                 break;
146             case COMMAND_STOP_ALERT_SERVICE:
147                 doStopAlertService(context);
148                 break;
149             case COMMAND_SELF_INDUCED_ANR:
150                 doSelfInducedAnr(context);
151                 break;
152             case COMMAND_START_ACTIVITY:
153                 doStartActivity(context, intent);
154                 break;
155             case COMMAND_STOP_ACTIVITY:
156                 doStopActivity(context, intent);
157                 break;
158             case COMMAND_CREATE_FGSL_PENDING_INTENT:
159                 doCreateFgslPendingIntent(context, intent);
160                 break;
161             case COMMAND_SEND_FGSL_PENDING_INTENT:
162                 doSendFgslPendingIntent(context, intent);
163                 break;
164             case COMMAND_BIND_FOREGROUND_SERVICE:
165                 doBindService(context, intent, FG_LOCATION_SERVICE_NAME);
166                 break;
167             case COMMAND_START_CHILD_PROCESS:
168                 doStartChildProcess(context, intent);
169                 break;
170             case COMMAND_STOP_CHILD_PROCESS:
171                 doStopChildProcess(context, intent);
172                 break;
173             case COMMAND_WAIT_FOR_CHILD_PROCESS_GONE:
174                 doWaitForChildProcessGone(context, intent);
175                 break;
176             case COMMAND_EMPTY:
177                 break;
178             case COMMAND_START_FOREGROUND_SERVICE_SPOOF_PACKAGE_NAME:
179                 doStartForegroundServiceSpoofPackageName(context, intent);
180                 break;
181         }
182     }
183 
doBindService(Context context, Intent commandIntent, String serviceName)184     private void doBindService(Context context, Intent commandIntent, String serviceName) {
185         String targetPackage = getTargetPackage(commandIntent);
186         int flags = getFlags(commandIntent);
187 
188         Intent bindIntent = new Intent();
189         bindIntent.setComponent(new ComponentName(targetPackage, serviceName));
190 
191         ServiceConnection connection = addServiceConnection(targetPackage);
192 
193         context.bindService(bindIntent, connection, flags | Context.BIND_AUTO_CREATE);
194     }
195 
doUnbindService(Context context, Intent commandIntent)196     private void doUnbindService(Context context, Intent commandIntent) {
197         String targetPackage = getTargetPackage(commandIntent);
198         context.unbindService(sServiceMap.remove(targetPackage));
199     }
200 
doStartForegroundService(Context context, Intent commandIntent)201     private void doStartForegroundService(Context context, Intent commandIntent) {
202         String targetPackage = getTargetPackage(commandIntent);
203         Intent fgsIntent = new Intent();
204         fgsIntent.putExtras(commandIntent);
205         fgsIntent.setComponent(new ComponentName(targetPackage, FG_SERVICE_NAME));
206         int command = LocalForegroundService.COMMAND_START_FOREGROUND;
207         fgsIntent.putExtras(LocalForegroundService.newCommand(command));
208         try {
209             context.startForegroundService(fgsIntent);
210         } catch (ForegroundServiceStartNotAllowedException e) {
211             Log.d(TAG, "startForegroundService gets an "
212                     + " ForegroundServiceStartNotAllowedException", e);
213         }
214     }
215 
doStartService(Context context, Intent commandIntent)216     private void doStartService(Context context, Intent commandIntent) {
217         String targetPackage = getTargetPackage(commandIntent);
218         Intent fgsIntent = new Intent();
219         fgsIntent.putExtras(commandIntent);
220         fgsIntent.setComponent(new ComponentName(targetPackage, FG_SERVICE_NAME));
221         context.startService(fgsIntent);
222     }
223 
doStartForegroundServiceWithType(Context context, Intent commandIntent)224     private void doStartForegroundServiceWithType(Context context, Intent commandIntent) {
225         String targetPackage = getTargetPackage(commandIntent);
226         Intent fgsIntent = new Intent();
227         fgsIntent.putExtras(commandIntent); // include the fg service type if any.
228         fgsIntent.setComponent(new ComponentName(targetPackage, FG_LOCATION_SERVICE_NAME));
229         int command = LocalForegroundServiceLocation.COMMAND_START_FOREGROUND_WITH_TYPE;
230         fgsIntent.putExtras(LocalForegroundService.newCommand(command));
231         try {
232             context.startForegroundService(fgsIntent);
233         } catch (ForegroundServiceStartNotAllowedException e) {
234             Log.d(TAG, "startForegroundService gets an "
235                     + "ForegroundServiceStartNotAllowedException", e);
236         }
237     }
238 
doStartForegroundServiceSticky(Context context, Intent commandIntent)239     private void doStartForegroundServiceSticky(Context context, Intent commandIntent) {
240         String targetPackage = getTargetPackage(commandIntent);
241         Intent fgsIntent = new Intent();
242         fgsIntent.putExtras(commandIntent);
243         fgsIntent.setComponent(new ComponentName(targetPackage, FG_STICKY_SERVICE_NAME));
244         int command = LocalForegroundService.COMMAND_START_FOREGROUND;
245         fgsIntent.putExtras(LocalForegroundService.newCommand(command));
246         try {
247             context.startForegroundService(fgsIntent);
248         } catch (ForegroundServiceStartNotAllowedException e) {
249             Log.d(TAG, "startForegroundService gets an "
250                     + "ForegroundServiceStartNotAllowedException", e);
251         }
252     }
253 
doStopService(Context context, Intent commandIntent, String serviceName)254     private void doStopService(Context context, Intent commandIntent,
255             String serviceName) {
256         String targetPackage = getTargetPackage(commandIntent);
257         Intent fgsIntent = new Intent();
258         fgsIntent.setComponent(new ComponentName(targetPackage, serviceName));
259         context.stopService(fgsIntent);
260     }
261 
doStartAlertService(Context context)262     private void doStartAlertService(Context context) {
263         Intent intent = new Intent(context, LocalAlertService.class);
264         intent.setAction(LocalAlertService.COMMAND_SHOW_ALERT);
265         context.startService(intent);
266     }
267 
doStopAlertService(Context context)268     private void doStopAlertService(Context context) {
269         Intent intent = new Intent(context, LocalAlertService.class);
270         intent.setAction(LocalAlertService.COMMAND_HIDE_ALERT);
271         context.startService(intent);
272     }
273 
doSelfInducedAnr(Context context)274     private void doSelfInducedAnr(Context context) {
275         ActivityManager am = context.getSystemService(ActivityManager.class);
276         am.appNotResponding("CTS - self induced");
277     }
278 
doStartActivity(Context context, Intent commandIntent)279     private void doStartActivity(Context context, Intent commandIntent) {
280         String targetPackage = getTargetPackage(commandIntent);
281         Intent activityIntent = new Intent(Intent.ACTION_MAIN);
282         sActivityIntent.put(targetPackage, activityIntent);
283         activityIntent.putExtras(commandIntent);
284         activityIntent.setComponent(new ComponentName(targetPackage, ACTIVITY_NAME));
285         activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
286         context.startActivity(activityIntent);
287     }
288 
doStopActivity(Context context, Intent commandIntent)289     private void doStopActivity(Context context, Intent commandIntent) {
290         String targetPackage = getTargetPackage(commandIntent);
291         Intent activityIntent = sActivityIntent.remove(targetPackage);
292         activityIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
293         activityIntent.putExtra("finish", true);
294         context.startActivity(activityIntent);
295     }
296 
doCreateFgslPendingIntent(Context context, Intent commandIntent)297     private void doCreateFgslPendingIntent(Context context, Intent commandIntent) {
298         final String targetPackage = getTargetPackage(commandIntent);
299         final Intent intent = new Intent().setComponent(
300                 new ComponentName(targetPackage, FG_LOCATION_SERVICE_NAME));
301         int command = LocalForegroundServiceLocation.COMMAND_START_FOREGROUND_WITH_TYPE;
302         intent.putExtras(LocalForegroundService.newCommand(command));
303         final PendingIntent pendingIntent = PendingIntent.getForegroundService(context, 0,
304                 intent, PendingIntent.FLAG_IMMUTABLE);
305         sPendingIntent.put(targetPackage, pendingIntent);
306     }
307 
doSendFgslPendingIntent(Context context, Intent commandIntent)308     private void doSendFgslPendingIntent(Context context, Intent commandIntent) {
309         final String targetPackage = getTargetPackage(commandIntent);
310         try {
311             ((PendingIntent) sPendingIntent.remove(targetPackage)).send();
312         } catch (PendingIntent.CanceledException e) {
313             Log.e(TAG, "Caugtht exception:", e);
314         }
315     }
316 
doStartChildProcess(Context context, Intent intent)317     private void doStartChildProcess(Context context, Intent intent) {
318         final Bundle extras = intent.getExtras();
319         final IBinder callback = extras.getBinder(EXTRA_CALLBACK);
320         final String[] cmdline = extras.getStringArray(EXTRA_CHILD_CMDLINE);
321         final Parcel data = Parcel.obtain();
322         final Parcel reply = Parcel.obtain();
323 
324         try {
325             sChildProcess = Runtime.getRuntime().exec(cmdline);
326             if (sChildProcess != null) {
327                 Log.i(TAG, "Forked child: " + sChildProcess);
328                 callback.transact(RESULT_CHILD_PROCESS_STARTED, data, reply, 0);
329             } // else the remote will fail with timeout
330         } catch (Exception e) {
331             Log.e(TAG, "Unable to execute command", e);
332             sChildProcess = null;
333         } finally {
334             data.recycle();
335             reply.recycle();
336         }
337     }
338 
doStopChildProcess(Context context, Intent intent)339     private void doStopChildProcess(Context context, Intent intent) {
340         final Bundle extras = intent.getExtras();
341         final IBinder callback = extras.getBinder(EXTRA_CALLBACK);
342         final long timeout = extras.getLong(EXTRA_TIMEOUT);
343         waitForChildProcessGone(true, callback, RESULT_CHILD_PROCESS_STOPPED, timeout);
344     }
345 
doWaitForChildProcessGone(Context context, Intent intent)346     private void doWaitForChildProcessGone(Context context, Intent intent) {
347         final Bundle extras = intent.getExtras();
348         final IBinder callback = extras.getBinder(EXTRA_CALLBACK);
349         final long timeout = extras.getLong(EXTRA_TIMEOUT);
350         waitForChildProcessGone(false, callback, RESULT_CHILD_PROCESS_GONE, timeout);
351     }
352 
waitForChildProcessGone(final boolean destroy, final IBinder callback, final int transactionCode, final long timeout)353     private static synchronized void waitForChildProcessGone(final boolean destroy,
354             final IBinder callback, final int transactionCode, final long timeout) {
355         if (destroy) {
356             sChildProcess.destroy();
357         }
358         new Thread(() -> {
359             final Parcel data = Parcel.obtain();
360             final Parcel reply = Parcel.obtain();
361             try {
362                 if (sChildProcess != null && sChildProcess.isAlive()) {
363                     final boolean exit = sChildProcess.waitFor(timeout, TimeUnit.MILLISECONDS);
364                     if (exit) {
365                         Log.i(TAG, "Child process died: " + sChildProcess);
366                         callback.transact(transactionCode, data, reply, 0);
367                     } else {
368                         Log.w(TAG, "Child process is still alive: " + sChildProcess);
369                     }
370                 } else {
371                     callback.transact(transactionCode, data, reply, 0);
372                 }
373             } catch (Exception e) {
374                 Log.e(TAG, "Error", e);
375             } finally {
376                 data.recycle();
377                 reply.recycle();
378             }
379         }).start();
380     }
381 
382     /**
383      * Directly call IActivityManager.startService() using a spoofed packageName which is known to
384      * be allowlisted by Android framework to be able to start foreground service
385      * from the background. Framework will disallow the foreground service to start from the
386      * background and a ForegroundServiceStartNotAllowedException will be caught.
387      * @param context
388      * @param commandIntent
389      */
doStartForegroundServiceSpoofPackageName(Context context, Intent commandIntent)390     private void doStartForegroundServiceSpoofPackageName(Context context, Intent commandIntent) {
391         String targetPackage = getTargetPackage(commandIntent);
392         Intent fgsIntent = new Intent();
393         fgsIntent.putExtras(commandIntent);
394         fgsIntent.setComponent(new ComponentName(targetPackage, FG_SERVICE_NAME));
395         int command = LocalForegroundService.COMMAND_START_FOREGROUND;
396         fgsIntent.putExtras(LocalForegroundService.newCommand(command));
397         try {
398             final PackageManager pm = context.getPackageManager();
399             String spoofPackageName = pm.getAttentionServicePackageName();
400             if (TextUtils.isEmpty(spoofPackageName)) {
401                 Log.d(TAG, "getAttentionServicePackageName() returns empty");
402                 spoofPackageName = pm.getSystemCaptionsServicePackageName();
403             }
404             if (TextUtils.isEmpty(spoofPackageName)) {
405                 Log.d(TAG, "getSystemCaptionsServicePackageName() returns empty");
406                 spoofPackageName = "android";
407             }
408             Log.d(TAG, "spoofPackageName: " + spoofPackageName);
409             final IBinder activityProxy = android.os.ServiceManager.getService("activity");
410             // Call IActivityManager.startService() directly using a spoofed packageName.
411             IActivityManager.Stub.asInterface(activityProxy).startService(
412                     context.getIApplicationThread(),
413                     fgsIntent,
414                     null,
415                     true,
416                     spoofPackageName,
417                     null,
418                     android.os.Process.myUserHandle().getIdentifier()
419             );
420         } catch (ForegroundServiceStartNotAllowedException e) {
421             Log.d(TAG, "startForegroundService gets an "
422                     + " ForegroundServiceStartNotAllowedException", e);
423         } catch (LinkageError e) {
424             // IActivityManager.startService() is a hidden API, access hidden API could get
425             // LinkageError, consider the test as pass if we get LinkageError.
426             Log.d(TAG, "startForegroundService gets an LinkageError", e);
427         } catch (RemoteException e) {
428             Log.d(TAG, "startForegroundService gets an RemoteException", e);
429         }
430     }
431 
getTargetPackage(Intent intent)432     private String getTargetPackage(Intent intent) {
433         return intent.getStringExtra(EXTRA_TARGET_PACKAGE);
434     }
435 
getFlags(Intent intent)436     private int getFlags(Intent intent) {
437         return intent.getIntExtra(EXTRA_FLAGS, 0);
438     }
439 
sendCommand(Context context, int command, String sourcePackage, String targetPackage, int flags, Bundle extras)440     public static void sendCommand(Context context, int command, String sourcePackage,
441             String targetPackage, int flags, Bundle extras) {
442         final Intent intent = makeIntent(command, sourcePackage, targetPackage, flags, extras);
443         Log.d(TAG, "Sending broadcast " + intent);
444         context.sendOrderedBroadcast(intent, null);
445     }
446 
sendCommandWithResultReceiver(Context context, int command, String sourcePackage, String targetPackage, int flags, Bundle extras, BroadcastReceiver resultReceiver)447     public static void sendCommandWithResultReceiver(Context context, int command,
448             String sourcePackage, String targetPackage, int flags, Bundle extras,
449             BroadcastReceiver resultReceiver) {
450         final Intent intent = makeIntent(command, sourcePackage, targetPackage, flags, extras);
451         Log.d(TAG, "Sending broadcast with result receiver " + intent);
452         context.sendOrderedBroadcast(intent, null, resultReceiver, null,
453                 Activity.RESULT_OK, null, null);
454     }
455 
sendCommandWithBroadcastOptions(Context context, int command, String sourcePackage, String targetPackage, int flags, Bundle extras, Bundle broadcastOptions)456     public static void sendCommandWithBroadcastOptions(Context context, int command,
457             String sourcePackage, String targetPackage, int flags, Bundle extras,
458             Bundle broadcastOptions) {
459         final Intent intent = makeIntent(command, sourcePackage, targetPackage, flags, extras);
460         Log.d(TAG, "Sending broadcast with BroadcastOptions " + intent);
461         context.sendOrderedBroadcast(intent, null, broadcastOptions, null, null, 0, null, null);
462     }
463 
makeIntent(int command, String sourcePackage, String targetPackage, int flags, Bundle extras)464     private static Intent makeIntent(int command, String sourcePackage,
465             String targetPackage, int flags, Bundle extras) {
466         Intent intent = new Intent();
467         if (command == COMMAND_BIND_SERVICE || command == COMMAND_START_FOREGROUND_SERVICE
468                 || command == COMMAND_STOP_FOREGROUND_SERVICE || command == COMMAND_START_ACTIVITY
469                 || command == COMMAND_START_FOREGROUND_SERVICE_LOCATION || command == COMMAND_UNBIND_SERVICE) {
470             intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
471         }
472         intent.setComponent(new ComponentName(sourcePackage, "android.app.stubs.CommandReceiver"));
473         intent.putExtra(EXTRA_COMMAND, command);
474         intent.putExtra(EXTRA_FLAGS, flags);
475         intent.putExtra(EXTRA_TARGET_PACKAGE, targetPackage);
476         if (extras != null) {
477             intent.putExtras(extras);
478         }
479         return intent;
480     }
481 
addServiceConnection(final String packageName)482     private ServiceConnection addServiceConnection(final String packageName) {
483         ServiceConnection connection = new ServiceConnection() {
484             @Override
485             public void onServiceConnected(ComponentName name, IBinder service) {
486             }
487 
488             @Override
489             public void onServiceDisconnected(ComponentName name) {
490             }
491         };
492         sServiceMap.put(packageName, connection);
493         return connection;
494     }
495 }
496