1 /* 2 * Copyright (C) 2010 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 com.android.internal.content; 18 19 import android.annotation.NonNull; 20 import android.app.Activity; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.pm.Flags; 26 import android.content.pm.PackageManager; 27 import android.net.Uri; 28 import android.os.Bundle; 29 import android.os.Handler; 30 import android.os.HandlerExecutor; 31 import android.os.IRemoteCallback; 32 import android.os.Looper; 33 import android.os.RemoteException; 34 import android.os.UserHandle; 35 import android.util.Log; 36 import android.util.Slog; 37 38 import com.android.internal.annotations.VisibleForTesting; 39 import com.android.internal.os.BackgroundThread; 40 41 import java.lang.ref.WeakReference; 42 import java.util.Objects; 43 import java.util.concurrent.Executor; 44 45 /** 46 * Helper class for monitoring the state of packages: adding, removing, 47 * updating, and disappearing and reappearing on the SD card. 48 */ 49 public abstract class PackageMonitor extends android.content.BroadcastReceiver { 50 static final String TAG = "PackageMonitor"; 51 52 Context mRegisteredContext; 53 Handler mRegisteredHandler; 54 String[] mDisappearingPackages; 55 String[] mAppearingPackages; 56 String[] mModifiedPackages; 57 int mChangeType; 58 int mChangeUserId = UserHandle.USER_NULL; 59 boolean mSomePackagesChanged; 60 String[] mModifiedComponents; 61 62 String[] mTempArray = new String[1]; 63 64 PackageMonitorCallback mPackageMonitorCallback; 65 66 private Executor mExecutor; 67 68 final boolean mSupportsPackageRestartQuery; 69 70 @UnsupportedAppUsage PackageMonitor()71 public PackageMonitor() { 72 // If the feature flag is enabled, set mSupportsPackageRestartQuery to false by default 73 this(!Flags.packageRestartQueryDisabledByDefault()); 74 } 75 76 /** 77 * The constructor of PackageMonitor whose parameters clearly indicate whether support 78 * querying package restart event. 79 */ PackageMonitor(boolean supportsPackageRestartQuery)80 public PackageMonitor(boolean supportsPackageRestartQuery) { 81 mSupportsPackageRestartQuery = supportsPackageRestartQuery; 82 } 83 getPackageFilter()84 private IntentFilter getPackageFilter() { 85 final boolean isCore = UserHandle.isCore(android.os.Process.myUid()); 86 87 IntentFilter filter = new IntentFilter(); 88 // Settings app sends the broadcast 89 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); 90 filter.addDataScheme("package"); 91 if (isCore) { 92 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 93 } 94 return filter; 95 } 96 97 @UnsupportedAppUsage register(Context context, Looper thread, boolean externalStorage)98 public void register(Context context, Looper thread, boolean externalStorage) { 99 register(context, thread, null, externalStorage); 100 } 101 102 @UnsupportedAppUsage register(Context context, Looper thread, UserHandle user, boolean externalStorage)103 public void register(Context context, Looper thread, UserHandle user, 104 boolean externalStorage) { 105 register(context, user, 106 (thread == null) ? BackgroundThread.getHandler() : new Handler(thread)); 107 } 108 109 /** 110 * Register for notifications of package changes such as install, removal and other events. 111 */ register(Context context, UserHandle user, Handler handler)112 public void register(Context context, UserHandle user, Handler handler) { 113 if (mRegisteredContext != null) { 114 throw new IllegalStateException("Already registered"); 115 } 116 mRegisteredContext = context; 117 mRegisteredHandler = Objects.requireNonNull(handler); 118 if (mSupportsPackageRestartQuery) { 119 final IntentFilter filter = getPackageFilter(); 120 if (user != null) { 121 context.registerReceiverAsUser(this, user, filter, null, mRegisteredHandler); 122 } else { 123 context.registerReceiver(this, filter, null, mRegisteredHandler); 124 } 125 } 126 if (mPackageMonitorCallback == null) { 127 PackageManager pm = mRegisteredContext.getPackageManager(); 128 if (pm != null) { 129 mExecutor = new HandlerExecutor(mRegisteredHandler); 130 mPackageMonitorCallback = new PackageMonitorCallback(this); 131 int userId = user != null ? user.getIdentifier() : mRegisteredContext.getUserId(); 132 pm.registerPackageMonitorCallback(mPackageMonitorCallback, userId); 133 } 134 } 135 } 136 getRegisteredHandler()137 public Handler getRegisteredHandler() { 138 return mRegisteredHandler; 139 } 140 141 @UnsupportedAppUsage unregister()142 public void unregister() { 143 if (mRegisteredContext == null) { 144 throw new IllegalStateException("Not registered"); 145 } 146 if (mSupportsPackageRestartQuery) { 147 mRegisteredContext.unregisterReceiver(this); 148 } 149 150 PackageManager pm = mRegisteredContext.getPackageManager(); 151 if (pm != null && mPackageMonitorCallback != null) { 152 pm.unregisterPackageMonitorCallback(mPackageMonitorCallback); 153 } 154 mPackageMonitorCallback = null; 155 mRegisteredContext = null; 156 mExecutor = null; 157 } 158 onBeginPackageChanges()159 public void onBeginPackageChanges() { 160 } 161 162 /** 163 * Called when a package is really added (and not replaced). 164 */ onPackageAdded(String packageName, int uid)165 public void onPackageAdded(String packageName, int uid) { 166 } 167 168 /** 169 * Same as {@link #onPackageAdded(String, int)}, but this callback 170 * has extras passed in. 171 */ onPackageAddedWithExtras(String packageName, int uid, Bundle extras)172 public void onPackageAddedWithExtras(String packageName, int uid, Bundle extras) { 173 } 174 175 /** 176 * Called when a package is really removed (and not replaced). 177 */ 178 @UnsupportedAppUsage onPackageRemoved(String packageName, int uid)179 public void onPackageRemoved(String packageName, int uid) { 180 } 181 182 /** 183 * Same as {@link #onPackageRemoved(String, int)}, but this callback 184 * has extras passed in. 185 */ onPackageRemovedWithExtras(String packageName, int uid, Bundle extras)186 public void onPackageRemovedWithExtras(String packageName, int uid, Bundle extras) { 187 } 188 189 /** 190 * Called when a package is really removed (and not replaced) for 191 * all users on the device. 192 */ onPackageRemovedAllUsers(String packageName, int uid)193 public void onPackageRemovedAllUsers(String packageName, int uid) { 194 } 195 196 /** 197 * Same as {@link #onPackageRemovedAllUsers(String, int)}, but this callback 198 * has extras passed in. 199 */ onPackageRemovedAllUsersWithExtras(String packageName, int uid, Bundle extras)200 public void onPackageRemovedAllUsersWithExtras(String packageName, int uid, Bundle extras) { 201 } 202 onPackageUpdateStarted(String packageName, int uid)203 public void onPackageUpdateStarted(String packageName, int uid) { 204 } 205 206 /** 207 * Same as {@link #onPackageUpdateStarted(String, int)}, but this callback 208 * has extras passed in. 209 */ onPackageUpdateStartedWithExtras(String packageName, int uid, Bundle extras)210 public void onPackageUpdateStartedWithExtras(String packageName, int uid, Bundle extras) { 211 } 212 onPackageUpdateFinished(String packageName, int uid)213 public void onPackageUpdateFinished(String packageName, int uid) { 214 } 215 216 /** 217 * Same as {@link #onPackageUpdateFinished(String, int)}, but this callback 218 * has extras passed in. 219 */ onPackageUpdateFinishedWithExtras(String packageName, int uid, Bundle extras)220 public void onPackageUpdateFinishedWithExtras(String packageName, int uid, Bundle extras) { 221 } 222 223 /** 224 * Direct reflection of {@link Intent#ACTION_PACKAGE_CHANGED 225 * Intent.ACTION_PACKAGE_CHANGED} being received, informing you of 226 * changes to the enabled/disabled state of components in a package 227 * and/or of the overall package. 228 * 229 * @param packageName The name of the package that is changing. 230 * @param uid The user ID the package runs under. 231 * @param components Any components in the package that are changing. If 232 * the overall package is changing, this will contain an entry of the 233 * package name itself. 234 * @return Return true to indicate you care about this change, which will 235 * result in {@link #onSomePackagesChanged()} being called later. If you 236 * return false, no further callbacks will happen about this change. The 237 * default implementation returns true if this is a change to the entire 238 * package. 239 */ 240 @UnsupportedAppUsage onPackageChanged(String packageName, int uid, String[] components)241 public boolean onPackageChanged(String packageName, int uid, String[] components) { 242 if (components != null) { 243 for (String name : components) { 244 if (packageName.equals(name)) { 245 return true; 246 } 247 } 248 } 249 return false; 250 } 251 252 /** 253 * Direct reflection of {@link Intent#ACTION_PACKAGE_CHANGED 254 * Intent.ACTION_PACKAGE_CHANGED} being received, this callback 255 * has extras passed in. 256 */ onPackageChangedWithExtras(String packageName, Bundle extras)257 public void onPackageChangedWithExtras(String packageName, Bundle extras) { 258 } 259 onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit, Bundle extras)260 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit, 261 Bundle extras) { 262 return onHandleForceStop(intent, packages, uid, doit); 263 } 264 onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit)265 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) { 266 return false; 267 } 268 onUidRemoved(int uid)269 public void onUidRemoved(int uid) { 270 } 271 onPackagesAvailable(String[] packages)272 public void onPackagesAvailable(String[] packages) { 273 } 274 onPackagesUnavailable(String[] packages)275 public void onPackagesUnavailable(String[] packages) { 276 } 277 onPackagesSuspended(String[] packages)278 public void onPackagesSuspended(String[] packages) { 279 } 280 onPackagesUnsuspended(String[] packages)281 public void onPackagesUnsuspended(String[] packages) { 282 } 283 284 public static final int PACKAGE_UNCHANGED = 0; 285 public static final int PACKAGE_UPDATING = 1; 286 public static final int PACKAGE_TEMPORARY_CHANGE = 2; 287 public static final int PACKAGE_PERMANENT_CHANGE = 3; 288 289 /** 290 * Called when a package disappears for any reason. 291 */ onPackageDisappeared(String packageName, int reason)292 public void onPackageDisappeared(String packageName, int reason) { 293 } 294 295 /** 296 * Called when a package disappears with extras passed in. 297 */ onPackageDisappearedWithExtras(String packageName, Bundle extras)298 public void onPackageDisappearedWithExtras(String packageName, Bundle extras) { 299 } 300 301 /** 302 * Called when a package appears for any reason. 303 */ onPackageAppeared(String packageName, int reason)304 public void onPackageAppeared(String packageName, int reason) { 305 } 306 307 308 /** 309 * Called when a package appears with extras passed in. 310 */ onPackageAppearedWithExtras(String packageName, Bundle extras)311 public void onPackageAppearedWithExtras(String packageName, Bundle extras) { 312 } 313 314 /** 315 * Called when an existing package is updated or its disabled state changes. 316 */ onPackageModified(@onNull String packageName)317 public void onPackageModified(@NonNull String packageName) { 318 } 319 320 /** 321 * Same as {@link #onPackageModified(String)}, but this callback 322 * has extras passed in. 323 */ onPackageModifiedWithExtras(@onNull String packageName, Bundle extras)324 public void onPackageModifiedWithExtras(@NonNull String packageName, Bundle extras) { 325 } 326 327 /** 328 * Called when a package in the stopped state is started for some reason. 329 * 330 * @param packageName Name of the package that was unstopped 331 * @param uid UID of the package that was unstopped 332 */ onPackageUnstopped(String packageName, int uid, Bundle extras)333 public void onPackageUnstopped(String packageName, int uid, Bundle extras) { 334 } 335 didSomePackagesChange()336 public boolean didSomePackagesChange() { 337 return mSomePackagesChanged; 338 } 339 isPackageAppearing(String packageName)340 public int isPackageAppearing(String packageName) { 341 if (mAppearingPackages != null) { 342 for (int i=mAppearingPackages.length-1; i>=0; i--) { 343 if (packageName.equals(mAppearingPackages[i])) { 344 return mChangeType; 345 } 346 } 347 } 348 return PACKAGE_UNCHANGED; 349 } 350 anyPackagesAppearing()351 public boolean anyPackagesAppearing() { 352 return mAppearingPackages != null; 353 } 354 355 @UnsupportedAppUsage isPackageDisappearing(String packageName)356 public int isPackageDisappearing(String packageName) { 357 if (mDisappearingPackages != null) { 358 for (int i=mDisappearingPackages.length-1; i>=0; i--) { 359 if (packageName.equals(mDisappearingPackages[i])) { 360 return mChangeType; 361 } 362 } 363 } 364 return PACKAGE_UNCHANGED; 365 } 366 anyPackagesDisappearing()367 public boolean anyPackagesDisappearing() { 368 return mDisappearingPackages != null; 369 } 370 isReplacing()371 public boolean isReplacing() { 372 return mChangeType == PACKAGE_UPDATING; 373 } 374 375 @UnsupportedAppUsage isPackageModified(String packageName)376 public boolean isPackageModified(String packageName) { 377 if (mModifiedPackages != null) { 378 for (int i=mModifiedPackages.length-1; i>=0; i--) { 379 if (packageName.equals(mModifiedPackages[i])) { 380 return true; 381 } 382 } 383 } 384 return false; 385 } 386 isComponentModified(String className)387 public boolean isComponentModified(String className) { 388 if (className == null || mModifiedComponents == null) { 389 return false; 390 } 391 for (int i = mModifiedComponents.length - 1; i >= 0; i--) { 392 if (className.equals(mModifiedComponents[i])) { 393 return true; 394 } 395 } 396 return false; 397 } 398 onSomePackagesChanged()399 public void onSomePackagesChanged() { 400 } 401 onFinishPackageChanges()402 public void onFinishPackageChanges() { 403 } 404 onPackageDataCleared(String packageName, int uid)405 public void onPackageDataCleared(String packageName, int uid) { 406 } 407 408 /** 409 * Callback to indicate the package's state has changed. 410 * @param packageName Name of an installed package 411 * @param uid The UID the package runs under. 412 */ onPackageStateChanged(String packageName, int uid)413 public void onPackageStateChanged(String packageName, int uid) {} 414 getChangingUserId()415 public int getChangingUserId() { 416 return mChangeUserId; 417 } 418 getPackageName(Intent intent)419 String getPackageName(Intent intent) { 420 Uri uri = intent.getData(); 421 String pkg = uri != null ? uri.getSchemeSpecificPart() : null; 422 return pkg; 423 } 424 425 @Override onReceive(Context context, Intent intent)426 public void onReceive(Context context, Intent intent) { 427 doHandlePackageEvent(intent); 428 } 429 430 postHandlePackageEvent(Intent intent)431 private void postHandlePackageEvent(Intent intent) { 432 if (mExecutor != null) { 433 mExecutor.execute(() -> doHandlePackageEvent(intent)); 434 } 435 } 436 437 /** 438 * Handle the package related event 439 * @param intent the intent that contains package related event information 440 */ 441 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) doHandlePackageEvent(Intent intent)442 public final void doHandlePackageEvent(Intent intent) { 443 mChangeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 444 UserHandle.USER_NULL); 445 if (mChangeUserId == UserHandle.USER_NULL) { 446 Slog.w(TAG, "Intent broadcast does not contain user handle: " + intent); 447 return; 448 } 449 onBeginPackageChanges(); 450 451 mDisappearingPackages = mAppearingPackages = null; 452 mSomePackagesChanged = false; 453 mModifiedComponents = null; 454 455 String action = intent.getAction(); 456 if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { 457 String pkg = getPackageName(intent); 458 int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); 459 // We consider something to have changed regardless of whether 460 // this is just an update, because the update is now finished 461 // and the contents of the package may have changed. 462 mSomePackagesChanged = true; 463 if (pkg != null) { 464 mAppearingPackages = mTempArray; 465 mTempArray[0] = pkg; 466 if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 467 mModifiedPackages = mTempArray; 468 mChangeType = PACKAGE_UPDATING; 469 onPackageUpdateFinished(pkg, uid); 470 onPackageUpdateFinishedWithExtras(pkg, uid, intent.getExtras()); 471 onPackageModified(pkg); 472 onPackageModifiedWithExtras(pkg, intent.getExtras()); 473 } else { 474 mChangeType = PACKAGE_PERMANENT_CHANGE; 475 onPackageAdded(pkg, uid); 476 onPackageAddedWithExtras(pkg, uid, intent.getExtras()); 477 } 478 onPackageAppearedWithExtras(pkg, intent.getExtras()); 479 onPackageAppeared(pkg, mChangeType); 480 } 481 } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { 482 String pkg = getPackageName(intent); 483 int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); 484 if (pkg != null) { 485 mDisappearingPackages = mTempArray; 486 mTempArray[0] = pkg; 487 if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 488 mChangeType = PACKAGE_UPDATING; 489 onPackageUpdateStarted(pkg, uid); 490 onPackageUpdateStartedWithExtras(pkg, uid, intent.getExtras()); 491 if (intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false)) { 492 // In case it is a removal event due to archiving, we trigger package 493 // update event to refresh details like icons, title etc. corresponding to 494 // the archived app. 495 onPackageModified(pkg); 496 onPackageModifiedWithExtras(pkg, intent.getExtras()); 497 } 498 } else { 499 mChangeType = PACKAGE_PERMANENT_CHANGE; 500 // We only consider something to have changed if this is 501 // not a replace; for a replace, we just need to consider 502 // it when it is re-added. 503 mSomePackagesChanged = true; 504 onPackageRemoved(pkg, uid); 505 onPackageRemovedWithExtras(pkg, uid, intent.getExtras()); 506 if (intent.getBooleanExtra(Intent.EXTRA_REMOVED_FOR_ALL_USERS, false)) { 507 onPackageRemovedAllUsers(pkg, uid); 508 onPackageRemovedAllUsersWithExtras(pkg, uid, intent.getExtras()); 509 } 510 } 511 onPackageDisappearedWithExtras(pkg, intent.getExtras()); 512 onPackageDisappeared(pkg, mChangeType); 513 } 514 } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) { 515 String pkg = getPackageName(intent); 516 int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); 517 mModifiedComponents = intent.getStringArrayExtra( 518 Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); 519 if (pkg != null) { 520 mModifiedPackages = mTempArray; 521 mTempArray[0] = pkg; 522 mChangeType = PACKAGE_PERMANENT_CHANGE; 523 if (onPackageChanged(pkg, uid, mModifiedComponents)) { 524 mSomePackagesChanged = true; 525 } 526 onPackageChangedWithExtras(pkg, intent.getExtras()); 527 onPackageModified(pkg); 528 onPackageModifiedWithExtras(pkg, intent.getExtras()); 529 } 530 } else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) { 531 String pkg = getPackageName(intent); 532 int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); 533 if (pkg != null) { 534 onPackageDataCleared(pkg, uid); 535 } 536 } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) { 537 mDisappearingPackages = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); 538 mChangeType = PACKAGE_TEMPORARY_CHANGE; 539 boolean canRestart = onHandleForceStop(intent, 540 mDisappearingPackages, 541 intent.getIntExtra(Intent.EXTRA_UID, 0), false, intent.getExtras()); 542 if (canRestart) setResultCode(Activity.RESULT_OK); 543 } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) { 544 mDisappearingPackages = new String[] {getPackageName(intent)}; 545 mChangeType = PACKAGE_TEMPORARY_CHANGE; 546 onHandleForceStop(intent, mDisappearingPackages, 547 intent.getIntExtra(Intent.EXTRA_UID, 0), true, intent.getExtras()); 548 } else if (Intent.ACTION_UID_REMOVED.equals(action)) { 549 onUidRemoved(intent.getIntExtra(Intent.EXTRA_UID, 0)); 550 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) { 551 String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 552 mAppearingPackages = pkgList; 553 mChangeType = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) 554 ? PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE; 555 mSomePackagesChanged = true; 556 if (pkgList != null) { 557 onPackagesAvailable(pkgList); 558 for (int i=0; i<pkgList.length; i++) { 559 onPackageAppeared(pkgList[i], mChangeType); 560 } 561 } 562 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { 563 String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 564 mDisappearingPackages = pkgList; 565 mChangeType = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) 566 ? PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE; 567 mSomePackagesChanged = true; 568 if (pkgList != null) { 569 onPackagesUnavailable(pkgList); 570 for (int i=0; i<pkgList.length; i++) { 571 onPackageDisappeared(pkgList[i], mChangeType); 572 } 573 } 574 } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) { 575 String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 576 mSomePackagesChanged = true; 577 onPackagesSuspended(pkgList); 578 } else if (Intent.ACTION_PACKAGES_UNSUSPENDED.equals(action)) { 579 String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); 580 mSomePackagesChanged = true; 581 onPackagesUnsuspended(pkgList); 582 } else if (Intent.ACTION_PACKAGE_UNSTOPPED.equals(action)) { 583 final String pkgName = getPackageName(intent); 584 mAppearingPackages = new String[] {pkgName}; 585 mChangeType = PACKAGE_TEMPORARY_CHANGE; 586 onPackageUnstopped(pkgName, intent.getIntExtra(Intent.EXTRA_UID, 0), 587 intent.getExtras()); 588 } 589 590 if (mSomePackagesChanged) { 591 onSomePackagesChanged(); 592 } 593 594 onFinishPackageChanges(); 595 mChangeUserId = UserHandle.USER_NULL; 596 } 597 598 private static final class PackageMonitorCallback extends IRemoteCallback.Stub { 599 private final WeakReference<PackageMonitor> mMonitorWeakReference; 600 PackageMonitorCallback(PackageMonitor monitor)601 PackageMonitorCallback(PackageMonitor monitor) { 602 mMonitorWeakReference = new WeakReference<>(monitor); 603 } 604 605 @Override sendResult(Bundle data)606 public void sendResult(Bundle data) throws RemoteException { 607 onHandlePackageMonitorCallback(data); 608 } 609 onHandlePackageMonitorCallback(Bundle bundle)610 private void onHandlePackageMonitorCallback(Bundle bundle) { 611 Intent intent = bundle.getParcelable( 612 PackageManager.EXTRA_PACKAGE_MONITOR_CALLBACK_RESULT, Intent.class); 613 if (intent == null) { 614 Log.w(TAG, "No intent is set for PackageMonitorCallback"); 615 return; 616 } 617 PackageMonitor monitor = mMonitorWeakReference.get(); 618 if (monitor != null) { 619 monitor.postHandlePackageEvent(intent); 620 } 621 } 622 } 623 } 624