1 /* 2 * Copyright (C) 2013 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.server.print; 18 19 import static android.content.pm.PackageManager.GET_SERVICES; 20 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; 21 22 import android.annotation.NonNull; 23 import android.app.ActivityManager; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.pm.UserInfo; 30 import android.database.ContentObserver; 31 import android.graphics.drawable.Icon; 32 import android.net.Uri; 33 import android.os.Binder; 34 import android.os.Bundle; 35 import android.os.Process; 36 import android.os.RemoteException; 37 import android.os.UserHandle; 38 import android.os.UserManager; 39 import android.print.IPrintDocumentAdapter; 40 import android.print.IPrintJobStateChangeListener; 41 import android.print.IPrintManager; 42 import android.print.IPrintServicesChangeListener; 43 import android.print.IPrinterDiscoveryObserver; 44 import android.print.PrintAttributes; 45 import android.print.PrintJobId; 46 import android.print.PrintJobInfo; 47 import android.print.PrintManager; 48 import android.print.PrinterId; 49 import android.printservice.PrintServiceInfo; 50 import android.printservice.recommendation.IRecommendationsChangeListener; 51 import android.printservice.recommendation.RecommendationInfo; 52 import android.provider.Settings; 53 import android.util.Log; 54 import android.util.SparseArray; 55 56 import com.android.internal.content.PackageMonitor; 57 import com.android.internal.os.BackgroundThread; 58 import com.android.internal.util.DumpUtils; 59 import com.android.internal.util.Preconditions; 60 import com.android.server.SystemService; 61 62 import java.io.FileDescriptor; 63 import java.io.PrintWriter; 64 import java.util.Iterator; 65 import java.util.List; 66 67 /** 68 * SystemService wrapper for the PrintManager implementation. Publishes 69 * Context.PRINT_SERVICE. 70 * PrintManager implementation is contained within. 71 */ 72 public final class PrintManagerService extends SystemService { 73 private static final String LOG_TAG = "PrintManagerService"; 74 75 private final PrintManagerImpl mPrintManagerImpl; 76 77 public PrintManagerService(Context context) { 78 super(context); 79 mPrintManagerImpl = new PrintManagerImpl(context); 80 } 81 82 @Override 83 public void onStart() { 84 publishBinderService(Context.PRINT_SERVICE, mPrintManagerImpl); 85 } 86 87 @Override 88 public void onUnlockUser(int userHandle) { 89 mPrintManagerImpl.handleUserUnlocked(userHandle); 90 } 91 92 @Override 93 public void onStopUser(int userHandle) { 94 mPrintManagerImpl.handleUserStopped(userHandle); 95 } 96 97 class PrintManagerImpl extends IPrintManager.Stub { 98 private static final int BACKGROUND_USER_ID = -10; 99 100 private final Object mLock = new Object(); 101 102 private final Context mContext; 103 104 private final UserManager mUserManager; 105 106 private final SparseArray<UserState> mUserStates = new SparseArray<>(); 107 108 PrintManagerImpl(Context context) { 109 mContext = context; 110 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 111 registerContentObservers(); 112 registerBroadcastReceivers(); 113 } 114 115 @Override 116 public Bundle print(String printJobName, IPrintDocumentAdapter adapter, 117 PrintAttributes attributes, String packageName, int appId, int userId) { 118 printJobName = Preconditions.checkStringNotEmpty(printJobName); 119 adapter = Preconditions.checkNotNull(adapter); 120 packageName = Preconditions.checkStringNotEmpty(packageName); 121 122 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 123 final int resolvedAppId; 124 final UserState userState; 125 final String resolvedPackageName; 126 synchronized (mLock) { 127 // Only the current group members can start new print jobs. 128 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 129 return null; 130 } 131 resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 132 resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName); 133 userState = getOrCreateUserStateLocked(resolvedUserId, false); 134 } 135 final long identity = Binder.clearCallingIdentity(); 136 try { 137 return userState.print(printJobName, adapter, attributes, 138 resolvedPackageName, resolvedAppId); 139 } finally { 140 Binder.restoreCallingIdentity(identity); 141 } 142 } 143 144 @Override 145 public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) { 146 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 147 final int resolvedAppId; 148 final UserState userState; 149 synchronized (mLock) { 150 // Only the current group members can query for state of print jobs. 151 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 152 return null; 153 } 154 resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 155 userState = getOrCreateUserStateLocked(resolvedUserId, false); 156 } 157 final long identity = Binder.clearCallingIdentity(); 158 try { 159 return userState.getPrintJobInfos(resolvedAppId); 160 } finally { 161 Binder.restoreCallingIdentity(identity); 162 } 163 } 164 165 @Override 166 public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) { 167 if (printJobId == null) { 168 return null; 169 } 170 171 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 172 final int resolvedAppId; 173 final UserState userState; 174 synchronized (mLock) { 175 // Only the current group members can query for state of a print job. 176 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 177 return null; 178 } 179 resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 180 userState = getOrCreateUserStateLocked(resolvedUserId, false); 181 } 182 final long identity = Binder.clearCallingIdentity(); 183 try { 184 return userState.getPrintJobInfo(printJobId, resolvedAppId); 185 } finally { 186 Binder.restoreCallingIdentity(identity); 187 } 188 } 189 190 @Override 191 public Icon getCustomPrinterIcon(PrinterId printerId, int userId) { 192 printerId = Preconditions.checkNotNull(printerId); 193 194 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 195 final UserState userState; 196 synchronized (mLock) { 197 // Only the current group members can get the printer icons. 198 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 199 return null; 200 } 201 userState = getOrCreateUserStateLocked(resolvedUserId, false); 202 } 203 final long identity = Binder.clearCallingIdentity(); 204 try { 205 return userState.getCustomPrinterIcon(printerId); 206 } finally { 207 Binder.restoreCallingIdentity(identity); 208 } 209 } 210 211 @Override 212 public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) { 213 if (printJobId == null) { 214 return; 215 } 216 217 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 218 final int resolvedAppId; 219 final UserState userState; 220 synchronized (mLock) { 221 // Only the current group members can cancel a print job. 222 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 223 return; 224 } 225 resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 226 userState = getOrCreateUserStateLocked(resolvedUserId, false); 227 } 228 final long identity = Binder.clearCallingIdentity(); 229 try { 230 userState.cancelPrintJob(printJobId, resolvedAppId); 231 } finally { 232 Binder.restoreCallingIdentity(identity); 233 } 234 } 235 236 @Override 237 public void restartPrintJob(PrintJobId printJobId, int appId, int userId) { 238 if (printJobId == null) { 239 return; 240 } 241 242 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 243 final int resolvedAppId; 244 final UserState userState; 245 synchronized (mLock) { 246 // Only the current group members can restart a print job. 247 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 248 return; 249 } 250 resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 251 userState = getOrCreateUserStateLocked(resolvedUserId, false); 252 } 253 final long identity = Binder.clearCallingIdentity(); 254 try { 255 userState.restartPrintJob(printJobId, resolvedAppId); 256 } finally { 257 Binder.restoreCallingIdentity(identity); 258 } 259 } 260 261 @Override 262 public List<PrintServiceInfo> getPrintServices(int selectionFlags, int userId) { 263 Preconditions.checkFlagsArgument(selectionFlags, 264 PrintManager.DISABLED_SERVICES | PrintManager.ENABLED_SERVICES); 265 266 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 267 final UserState userState; 268 synchronized (mLock) { 269 // Only the current group members can get print services. 270 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 271 return null; 272 } 273 userState = getOrCreateUserStateLocked(resolvedUserId, false); 274 } 275 final long identity = Binder.clearCallingIdentity(); 276 try { 277 return userState.getPrintServices(selectionFlags); 278 } finally { 279 Binder.restoreCallingIdentity(identity); 280 } 281 } 282 283 @Override 284 public void setPrintServiceEnabled(ComponentName service, boolean isEnabled, int userId) { 285 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 286 final int appId = UserHandle.getAppId(Binder.getCallingUid()); 287 288 try { 289 if (appId != Process.SYSTEM_UID && appId != UserHandle.getAppId( 290 mContext.getPackageManager().getPackageUidAsUser( 291 PrintManager.PRINT_SPOOLER_PACKAGE_NAME, resolvedUserId))) { 292 throw new SecurityException("Only system and print spooler can call this"); 293 } 294 } catch (PackageManager.NameNotFoundException e) { 295 Log.e(LOG_TAG, "Could not verify caller", e); 296 return; 297 } 298 299 service = Preconditions.checkNotNull(service); 300 301 final UserState userState; 302 synchronized (mLock) { 303 // Only the current group members can enable / disable services. 304 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 305 return; 306 } 307 userState = getOrCreateUserStateLocked(resolvedUserId, false); 308 } 309 final long identity = Binder.clearCallingIdentity(); 310 try { 311 userState.setPrintServiceEnabled(service, isEnabled); 312 } finally { 313 Binder.restoreCallingIdentity(identity); 314 } 315 } 316 317 @Override 318 public List<RecommendationInfo> getPrintServiceRecommendations(int userId) { 319 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 320 final UserState userState; 321 synchronized (mLock) { 322 // Only the current group members can get print service recommendations. 323 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 324 return null; 325 } 326 userState = getOrCreateUserStateLocked(resolvedUserId, false); 327 } 328 final long identity = Binder.clearCallingIdentity(); 329 try { 330 return userState.getPrintServiceRecommendations(); 331 } finally { 332 Binder.restoreCallingIdentity(identity); 333 } 334 } 335 336 @Override 337 public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer, 338 int userId) { 339 observer = Preconditions.checkNotNull(observer); 340 341 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 342 final UserState userState; 343 synchronized (mLock) { 344 // Only the current group members can create a discovery session. 345 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 346 return; 347 } 348 userState = getOrCreateUserStateLocked(resolvedUserId, false); 349 } 350 final long identity = Binder.clearCallingIdentity(); 351 try { 352 userState.createPrinterDiscoverySession(observer); 353 } finally { 354 Binder.restoreCallingIdentity(identity); 355 } 356 } 357 358 @Override 359 public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer, 360 int userId) { 361 observer = Preconditions.checkNotNull(observer); 362 363 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 364 final UserState userState; 365 synchronized (mLock) { 366 // Only the current group members can destroy a discovery session. 367 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 368 return; 369 } 370 userState = getOrCreateUserStateLocked(resolvedUserId, false); 371 } 372 final long identity = Binder.clearCallingIdentity(); 373 try { 374 userState.destroyPrinterDiscoverySession(observer); 375 } finally { 376 Binder.restoreCallingIdentity(identity); 377 } 378 } 379 380 @Override 381 public void startPrinterDiscovery(IPrinterDiscoveryObserver observer, 382 List<PrinterId> priorityList, int userId) { 383 observer = Preconditions.checkNotNull(observer); 384 if (priorityList != null) { 385 priorityList = Preconditions.checkCollectionElementsNotNull(priorityList, 386 "PrinterId"); 387 } 388 389 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 390 final UserState userState; 391 synchronized (mLock) { 392 // Only the current group members can start discovery. 393 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 394 return; 395 } 396 userState = getOrCreateUserStateLocked(resolvedUserId, false); 397 } 398 final long identity = Binder.clearCallingIdentity(); 399 try { 400 userState.startPrinterDiscovery(observer, priorityList); 401 } finally { 402 Binder.restoreCallingIdentity(identity); 403 } 404 } 405 406 @Override 407 public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) { 408 observer = Preconditions.checkNotNull(observer); 409 410 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 411 final UserState userState; 412 synchronized (mLock) { 413 // Only the current group members can stop discovery. 414 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 415 return; 416 } 417 userState = getOrCreateUserStateLocked(resolvedUserId, false); 418 } 419 final long identity = Binder.clearCallingIdentity(); 420 try { 421 userState.stopPrinterDiscovery(observer); 422 } finally { 423 Binder.restoreCallingIdentity(identity); 424 } 425 } 426 427 @Override 428 public void validatePrinters(List<PrinterId> printerIds, int userId) { 429 printerIds = Preconditions.checkCollectionElementsNotNull(printerIds, "PrinterId"); 430 431 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 432 final UserState userState; 433 synchronized (mLock) { 434 // Only the current group members can validate printers. 435 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 436 return; 437 } 438 userState = getOrCreateUserStateLocked(resolvedUserId, false); 439 } 440 final long identity = Binder.clearCallingIdentity(); 441 try { 442 userState.validatePrinters(printerIds); 443 } finally { 444 Binder.restoreCallingIdentity(identity); 445 } 446 } 447 448 @Override 449 public void startPrinterStateTracking(PrinterId printerId, int userId) { 450 printerId = Preconditions.checkNotNull(printerId); 451 452 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 453 final UserState userState; 454 synchronized (mLock) { 455 // Only the current group members can start printer tracking. 456 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 457 return; 458 } 459 userState = getOrCreateUserStateLocked(resolvedUserId, false); 460 } 461 final long identity = Binder.clearCallingIdentity(); 462 try { 463 userState.startPrinterStateTracking(printerId); 464 } finally { 465 Binder.restoreCallingIdentity(identity); 466 } 467 } 468 469 @Override 470 public void stopPrinterStateTracking(PrinterId printerId, int userId) { 471 printerId = Preconditions.checkNotNull(printerId); 472 473 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 474 final UserState userState; 475 synchronized (mLock) { 476 // Only the current group members can stop printer tracking. 477 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 478 return; 479 } 480 userState = getOrCreateUserStateLocked(resolvedUserId, false); 481 } 482 final long identity = Binder.clearCallingIdentity(); 483 try { 484 userState.stopPrinterStateTracking(printerId); 485 } finally { 486 Binder.restoreCallingIdentity(identity); 487 } 488 } 489 490 @Override 491 public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener, 492 int appId, int userId) throws RemoteException { 493 listener = Preconditions.checkNotNull(listener); 494 495 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 496 final int resolvedAppId; 497 final UserState userState; 498 synchronized (mLock) { 499 // Only the current group members can add a print job listener. 500 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 501 return; 502 } 503 resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 504 userState = getOrCreateUserStateLocked(resolvedUserId, false); 505 } 506 final long identity = Binder.clearCallingIdentity(); 507 try { 508 userState.addPrintJobStateChangeListener(listener, resolvedAppId); 509 } finally { 510 Binder.restoreCallingIdentity(identity); 511 } 512 } 513 514 @Override 515 public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener, 516 int userId) { 517 listener = Preconditions.checkNotNull(listener); 518 519 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 520 final UserState userState; 521 synchronized (mLock) { 522 // Only the current group members can remove a print job listener. 523 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 524 return; 525 } 526 userState = getOrCreateUserStateLocked(resolvedUserId, false); 527 } 528 final long identity = Binder.clearCallingIdentity(); 529 try { 530 userState.removePrintJobStateChangeListener(listener); 531 } finally { 532 Binder.restoreCallingIdentity(identity); 533 } 534 } 535 536 @Override 537 public void addPrintServicesChangeListener(IPrintServicesChangeListener listener, 538 int userId) throws RemoteException { 539 listener = Preconditions.checkNotNull(listener); 540 541 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 542 final UserState userState; 543 synchronized (mLock) { 544 // Only the current group members can add a print services listener. 545 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 546 return; 547 } 548 userState = getOrCreateUserStateLocked(resolvedUserId, false); 549 } 550 final long identity = Binder.clearCallingIdentity(); 551 try { 552 userState.addPrintServicesChangeListener(listener); 553 } finally { 554 Binder.restoreCallingIdentity(identity); 555 } 556 } 557 558 @Override 559 public void removePrintServicesChangeListener(IPrintServicesChangeListener listener, 560 int userId) { 561 listener = Preconditions.checkNotNull(listener); 562 563 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 564 final UserState userState; 565 synchronized (mLock) { 566 // Only the current group members can remove a print services change listener. 567 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 568 return; 569 } 570 userState = getOrCreateUserStateLocked(resolvedUserId, false); 571 } 572 final long identity = Binder.clearCallingIdentity(); 573 try { 574 userState.removePrintServicesChangeListener(listener); 575 } finally { 576 Binder.restoreCallingIdentity(identity); 577 } 578 } 579 580 @Override 581 public void addPrintServiceRecommendationsChangeListener( 582 IRecommendationsChangeListener listener, int userId) 583 throws RemoteException { 584 listener = Preconditions.checkNotNull(listener); 585 586 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 587 final UserState userState; 588 synchronized (mLock) { 589 // Only the current group members can add a print service recommendations listener. 590 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 591 return; 592 } 593 userState = getOrCreateUserStateLocked(resolvedUserId, false); 594 } 595 final long identity = Binder.clearCallingIdentity(); 596 try { 597 userState.addPrintServiceRecommendationsChangeListener(listener); 598 } finally { 599 Binder.restoreCallingIdentity(identity); 600 } 601 } 602 603 @Override 604 public void removePrintServiceRecommendationsChangeListener( 605 IRecommendationsChangeListener listener, int userId) { 606 listener = Preconditions.checkNotNull(listener); 607 608 final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 609 final UserState userState; 610 synchronized (mLock) { 611 // Only the current group members can remove a print service recommendations 612 // listener. 613 if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { 614 return; 615 } 616 userState = getOrCreateUserStateLocked(resolvedUserId, false); 617 } 618 final long identity = Binder.clearCallingIdentity(); 619 try { 620 userState.removePrintServiceRecommendationsChangeListener(listener); 621 } finally { 622 Binder.restoreCallingIdentity(identity); 623 } 624 } 625 626 @Override 627 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 628 fd = Preconditions.checkNotNull(fd); 629 pw = Preconditions.checkNotNull(pw); 630 631 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 632 633 synchronized (mLock) { 634 final long identity = Binder.clearCallingIdentity(); 635 try { 636 pw.println("PRINT MANAGER STATE (dumpsys print)"); 637 final int userStateCount = mUserStates.size(); 638 for (int i = 0; i < userStateCount; i++) { 639 UserState userState = mUserStates.valueAt(i); 640 userState.dump(fd, pw, ""); 641 pw.println(); 642 } 643 } finally { 644 Binder.restoreCallingIdentity(identity); 645 } 646 } 647 } 648 649 private void registerContentObservers() { 650 final Uri enabledPrintServicesUri = Settings.Secure.getUriFor( 651 Settings.Secure.DISABLED_PRINT_SERVICES); 652 ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) { 653 @Override 654 public void onChange(boolean selfChange, Uri uri, int userId) { 655 if (enabledPrintServicesUri.equals(uri)) { 656 synchronized (mLock) { 657 final int userCount = mUserStates.size(); 658 for (int i = 0; i < userCount; i++) { 659 if (userId == UserHandle.USER_ALL 660 || userId == mUserStates.keyAt(i)) { 661 mUserStates.valueAt(i).updateIfNeededLocked(); 662 } 663 } 664 } 665 } 666 } 667 }; 668 669 mContext.getContentResolver().registerContentObserver(enabledPrintServicesUri, 670 false, observer, UserHandle.USER_ALL); 671 } 672 673 private void registerBroadcastReceivers() { 674 PackageMonitor monitor = new PackageMonitor() { 675 /** 676 * Checks if the package contains a print service. 677 * 678 * @param packageName The name of the package 679 * 680 * @return true iff the package contains a print service 681 */ 682 private boolean hasPrintService(String packageName) { 683 Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE); 684 intent.setPackage(packageName); 685 686 List<ResolveInfo> installedServices = mContext.getPackageManager() 687 .queryIntentServicesAsUser(intent, 688 GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING, 689 getChangingUserId()); 690 691 return installedServices != null && !installedServices.isEmpty(); 692 } 693 694 /** 695 * Checks if there is a print service currently registered for this package. 696 * 697 * @param userState The userstate for the current user 698 * @param packageName The name of the package 699 * 700 * @return true iff the package contained (and might still contain) a print service 701 */ 702 private boolean hadPrintService(@NonNull UserState userState, String packageName) { 703 List<PrintServiceInfo> installedServices = userState 704 .getPrintServices(PrintManager.ALL_SERVICES); 705 706 if (installedServices == null) { 707 return false; 708 } 709 710 final int numInstalledServices = installedServices.size(); 711 for (int i = 0; i < numInstalledServices; i++) { 712 if (installedServices.get(i).getResolveInfo().serviceInfo.packageName 713 .equals(packageName)) { 714 return true; 715 } 716 } 717 718 return false; 719 } 720 721 @Override 722 public void onPackageModified(String packageName) { 723 if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return; 724 UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false, 725 false /* enforceUserUnlockingOrUnlocked */); 726 727 synchronized (mLock) { 728 if (hadPrintService(userState, packageName) 729 || hasPrintService(packageName)) { 730 userState.updateIfNeededLocked(); 731 } 732 } 733 734 userState.prunePrintServices(); 735 } 736 737 @Override 738 public void onPackageRemoved(String packageName, int uid) { 739 if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return; 740 UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false, 741 false /* enforceUserUnlockingOrUnlocked */); 742 743 synchronized (mLock) { 744 if (hadPrintService(userState, packageName)) { 745 userState.updateIfNeededLocked(); 746 } 747 } 748 749 userState.prunePrintServices(); 750 } 751 752 @Override 753 public boolean onHandleForceStop(Intent intent, String[] stoppedPackages, 754 int uid, boolean doit) { 755 if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return false; 756 synchronized (mLock) { 757 // A background user/profile's print jobs are running but there is 758 // no UI shown. Hence, if the packages of such a user change we need 759 // to handle it as the change may affect ongoing print jobs. 760 UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false, 761 false /* enforceUserUnlockingOrUnlocked */); 762 boolean stoppedSomePackages = false; 763 764 List<PrintServiceInfo> enabledServices = userState 765 .getPrintServices(PrintManager.ENABLED_SERVICES); 766 if (enabledServices == null) { 767 return false; 768 } 769 770 Iterator<PrintServiceInfo> iterator = enabledServices.iterator(); 771 while (iterator.hasNext()) { 772 ComponentName componentName = iterator.next().getComponentName(); 773 String componentPackage = componentName.getPackageName(); 774 for (String stoppedPackage : stoppedPackages) { 775 if (componentPackage.equals(stoppedPackage)) { 776 if (!doit) { 777 return true; 778 } 779 stoppedSomePackages = true; 780 break; 781 } 782 } 783 } 784 if (stoppedSomePackages) { 785 userState.updateIfNeededLocked(); 786 } 787 return false; 788 } 789 } 790 791 @Override 792 public void onPackageAdded(String packageName, int uid) { 793 if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return; 794 synchronized (mLock) { 795 if (hasPrintService(packageName)) { 796 UserState userState = getOrCreateUserStateLocked(getChangingUserId(), 797 false, false /* enforceUserUnlockingOrUnlocked */); 798 userState.updateIfNeededLocked(); 799 } 800 } 801 } 802 }; 803 804 // package changes 805 monitor.register(mContext, BackgroundThread.getHandler().getLooper(), 806 UserHandle.ALL, true); 807 } 808 private UserState getOrCreateUserStateLocked(int userId, boolean lowPriority) { 809 return getOrCreateUserStateLocked(userId, lowPriority, 810 true /* enforceUserUnlockingOrUnlocked */); 811 } 812 813 private UserState getOrCreateUserStateLocked(int userId, boolean lowPriority, 814 boolean enforceUserUnlockingOrUnlocked) { 815 if (enforceUserUnlockingOrUnlocked && !mUserManager.isUserUnlockingOrUnlocked(userId)) { 816 throw new IllegalStateException( 817 "User " + userId + " must be unlocked for printing to be available"); 818 } 819 820 UserState userState = mUserStates.get(userId); 821 if (userState == null) { 822 userState = new UserState(mContext, userId, mLock, lowPriority); 823 mUserStates.put(userId, userState); 824 } 825 826 if (!lowPriority) { 827 userState.increasePriority(); 828 } 829 830 return userState; 831 } 832 833 private void handleUserUnlocked(final int userId) { 834 // This code will touch the remote print spooler which 835 // must be called off the main thread, so post the work. 836 BackgroundThread.getHandler().post(new Runnable() { 837 @Override 838 public void run() { 839 if (!mUserManager.isUserUnlockingOrUnlocked(userId)) return; 840 841 UserState userState; 842 synchronized (mLock) { 843 userState = getOrCreateUserStateLocked(userId, true, 844 false /*enforceUserUnlockingOrUnlocked */); 845 userState.updateIfNeededLocked(); 846 } 847 // This is the first time we switch to this user after boot, so 848 // now is the time to remove obsolete print jobs since they 849 // are from the last boot and no application would query them. 850 userState.removeObsoletePrintJobs(); 851 } 852 }); 853 } 854 855 private void handleUserStopped(final int userId) { 856 // This code will touch the remote print spooler which 857 // must be called off the main thread, so post the work. 858 BackgroundThread.getHandler().post(new Runnable() { 859 @Override 860 public void run() { 861 synchronized (mLock) { 862 UserState userState = mUserStates.get(userId); 863 if (userState != null) { 864 userState.destroyLocked(); 865 mUserStates.remove(userId); 866 } 867 } 868 } 869 }); 870 } 871 872 private int resolveCallingProfileParentLocked(int userId) { 873 if (userId != getCurrentUserId()) { 874 final long identity = Binder.clearCallingIdentity(); 875 try { 876 UserInfo parent = mUserManager.getProfileParent(userId); 877 if (parent != null) { 878 return parent.getUserHandle().getIdentifier(); 879 } else { 880 return BACKGROUND_USER_ID; 881 } 882 } finally { 883 Binder.restoreCallingIdentity(identity); 884 } 885 } 886 return userId; 887 } 888 889 private int resolveCallingAppEnforcingPermissions(int appId) { 890 final int callingUid = Binder.getCallingUid(); 891 if (callingUid == 0 || callingUid == Process.SYSTEM_UID 892 || callingUid == Process.SHELL_UID) { 893 return appId; 894 } 895 final int callingAppId = UserHandle.getAppId(callingUid); 896 if (appId == callingAppId) { 897 return appId; 898 } 899 if (mContext.checkCallingPermission( 900 "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS") 901 != PackageManager.PERMISSION_GRANTED) { 902 throw new SecurityException("Call from app " + callingAppId + " as app " 903 + appId + " without com.android.printspooler.permission" 904 + ".ACCESS_ALL_PRINT_JOBS"); 905 } 906 return appId; 907 } 908 909 private int resolveCallingUserEnforcingPermissions(int userId) { 910 try { 911 return ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(), 912 Binder.getCallingUid(), userId, true, true, "", null); 913 } catch (RemoteException re) { 914 // Shouldn't happen, local. 915 } 916 return userId; 917 } 918 919 private @NonNull String resolveCallingPackageNameEnforcingSecurity( 920 @NonNull String packageName) { 921 String[] packages = mContext.getPackageManager().getPackagesForUid( 922 Binder.getCallingUid()); 923 final int packageCount = packages.length; 924 for (int i = 0; i < packageCount; i++) { 925 if (packageName.equals(packages[i])) { 926 return packageName; 927 } 928 } 929 throw new IllegalArgumentException("packageName has to belong to the caller"); 930 } 931 932 private int getCurrentUserId () { 933 final long identity = Binder.clearCallingIdentity(); 934 try { 935 return ActivityManager.getCurrentUser(); 936 } finally { 937 Binder.restoreCallingIdentity(identity); 938 } 939 } 940 } 941 } 942