14b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/* 24b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Copyright (C) 2013 The Android Open Source Project 34b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 44b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 54b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * you may not use this file except in compliance with the License. 64b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * You may obtain a copy of the License at 74b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 84b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 94b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * See the License for the specific language governing permissions and 144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * limitations under the License. 154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpackage com.android.server.print; 184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.Manifest; 20d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.app.Notification; 21d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.app.NotificationManager; 22d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.app.PendingIntent; 234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.BroadcastReceiver; 244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.ComponentName; 254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Context; 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Intent; 274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentFilter; 284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.pm.PackageManager; 29d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.content.pm.ResolveInfo; 30d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.content.pm.ServiceInfo; 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.database.ContentObserver; 324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.net.Uri; 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Binder; 347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslavimport android.os.Bundle; 354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Process; 36704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport android.os.RemoteException; 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.UserHandle; 38a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintDocumentAdapter; 39704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport android.print.IPrintJobStateChangeListener; 404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.IPrintManager; 4144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganovimport android.print.IPrinterDiscoveryObserver; 424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes; 432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport android.print.PrintJobId; 444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintJobInfo; 4544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganovimport android.print.PrinterId; 46860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganovimport android.printservice.PrintServiceInfo; 474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.provider.Settings; 487bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslavimport android.text.TextUtils; 49a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.util.SparseArray; 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 51d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport com.android.internal.R; 524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.internal.content.PackageMonitor; 53a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport com.android.internal.os.BackgroundThread; 544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 55b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.FileDescriptor; 56b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.PrintWriter; 574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Iterator; 584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List; 594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Set; 604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintManagerService extends IPrintManager.Stub { 624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private static final char COMPONENT_NAME_SEPARATOR = ':'; 644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 65d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME = 66d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav "EXTRA_PRINT_SERVICE_COMPONENT_NAME"; 67d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Object mLock = new Object(); 694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Context mContext; 714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 72a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private int mCurrentUserId = UserHandle.USER_OWNER; 754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintManagerService(Context context) { 774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mContext = context; 784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov registerContentObservers(); 79a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov registerBoradcastReceivers(); 80a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 81a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void systemRuning() { 83a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov BackgroundThread.getHandler().post(new Runnable() { 84a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 85a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void run() { 862fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav final UserState userState; 87a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 882fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState = getCurrentUserStateLocked(); 89a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState.updateIfNeededLocked(); 90a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 912fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav // This is the first time we switch to this user after boot, so 922fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav // now is the time to remove obsolete print jobs since they 932fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav // are from the last boot and no application would query them. 942fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState.removeObsoletePrintJobs(); 95a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 96a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov }); 974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1007bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public Bundle print(String printJobName, IPrintDocumentAdapter adapter, 1017bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintAttributes attributes, String packageName, int appId, int userId) { 102a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 103a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 1047bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav String resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName); 105a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final UserState userState; 106a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 107a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 108a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 1117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return userState.print(printJobName, adapter, attributes, 1127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav resolvedPackageName, resolvedAppId); 1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } finally { 1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Binder.restoreCallingIdentity(identity); 1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 119a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) { 120a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 121a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 122a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final UserState userState; 123a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 124a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 125a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 1282fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return userState.getPrintJobInfos(resolvedAppId); 1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } finally { 1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Binder.restoreCallingIdentity(identity); 1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1352fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) { 136a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 137a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 138a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final UserState userState; 139a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 140a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 141a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 1442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return userState.getPrintJobInfo(printJobId, resolvedAppId); 1454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } finally { 1464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Binder.restoreCallingIdentity(identity); 1474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) { 152a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 153a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 154a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final UserState userState; 155a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 156a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 157a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 1584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 1594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 1602fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState.cancelPrintJob(printJobId, resolvedAppId); 1618c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov } finally { 1628c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov Binder.restoreCallingIdentity(identity); 1638c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov } 1648c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov } 1658c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov 1668c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov @Override 1672fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void restartPrintJob(PrintJobId printJobId, int appId, int userId) { 1688c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 1698c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 1702fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav final UserState userState; 1718c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov synchronized (mLock) { 1722fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState = getOrCreateUserStateLocked(resolvedUserId); 1738c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov } 1748c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 1758c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov try { 1762fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState.restartPrintJob(printJobId, resolvedAppId); 1774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } finally { 1784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Binder.restoreCallingIdentity(identity); 1794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 182860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov @Override 183860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov public List<PrintServiceInfo> getEnabledPrintServices(int userId) { 184860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 185860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov final UserState userState; 186860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov synchronized (mLock) { 187860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 188860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 189860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 190860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov try { 191860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov return userState.getEnabledPrintServices(); 192860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } finally { 193860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov Binder.restoreCallingIdentity(identity); 194860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 195860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 196860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov 19744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov @Override 198d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav public List<PrintServiceInfo> getInstalledPrintServices(int userId) { 199d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 200d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav final UserState userState; 201d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav synchronized (mLock) { 202d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav userState = getOrCreateUserStateLocked(resolvedUserId); 203d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 204d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav final long identity = Binder.clearCallingIdentity(); 205d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav try { 206d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav return userState.getInstalledPrintServices(); 207d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } finally { 208d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav Binder.restoreCallingIdentity(identity); 209d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 210d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 211d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav 212d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav @Override 21344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer, 21444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov int userId) { 21544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 21644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final UserState userState; 21744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov synchronized (mLock) { 21844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 21944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 22044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 22144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov try { 22244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState.createPrinterDiscoverySession(observer); 22344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } finally { 22444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Binder.restoreCallingIdentity(identity); 22544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 22644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 22744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 22844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov @Override 22944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer, 23044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov int userId) { 23144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 23244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final UserState userState; 23344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov synchronized (mLock) { 23444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 23544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 23644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 23744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov try { 23844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState.destroyPrinterDiscoverySession(observer); 23944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } finally { 24044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Binder.restoreCallingIdentity(identity); 24144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 24244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 24344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 24444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov @Override 24544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov public void startPrinterDiscovery(IPrinterDiscoveryObserver observer, 24644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov List<PrinterId> priorityList, int userId) { 24744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 24844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final UserState userState; 24944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov synchronized (mLock) { 25044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 25144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 25244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 25344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov try { 25444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState.startPrinterDiscovery(observer, priorityList); 25544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } finally { 25644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Binder.restoreCallingIdentity(identity); 25744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 25844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 25944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 26044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov @Override 26144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) { 26244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 26344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final UserState userState; 26444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov synchronized (mLock) { 26544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 26644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 26744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 26844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov try { 26944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState.stopPrinterDiscovery(observer); 27044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } finally { 27144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Binder.restoreCallingIdentity(identity); 27244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 27344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 27444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 27544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov @Override 276d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public void validatePrinters(List<PrinterId> printerIds, int userId) { 27744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 27844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final UserState userState; 27944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov synchronized (mLock) { 28044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 28144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 28244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 28344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov try { 284d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov userState.validatePrinters(printerIds); 285d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } finally { 286d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov Binder.restoreCallingIdentity(identity); 287d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 288d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 289d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 290d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov @Override 291d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public void startPrinterStateTracking(PrinterId printerId, int userId) { 292d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 293d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov final UserState userState; 294d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov synchronized (mLock) { 295d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 296d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 297d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 298d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov try { 299d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov userState.startPrinterStateTracking(printerId); 300d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } finally { 301d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov Binder.restoreCallingIdentity(identity); 302d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 303d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 304d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 305d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov @Override 306d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public void stopPrinterStateTracking(PrinterId printerId, int userId) { 307d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 308d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov final UserState userState; 309d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov synchronized (mLock) { 310d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 311d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 312d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 313d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov try { 314d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov userState.stopPrinterStateTracking(printerId); 31544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } finally { 31644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov Binder.restoreCallingIdentity(identity); 31744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 31844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 31944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 320b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov @Override 321704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener, 322704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov int appId, int userId) throws RemoteException { 323704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 324704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId); 325704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final UserState userState; 326704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov synchronized (mLock) { 327704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 328704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 329704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 330704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 331704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov userState.addPrintJobStateChangeListener(listener, resolvedAppId); 332704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } finally { 333704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Binder.restoreCallingIdentity(identity); 334704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 335704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 336704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 337704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov @Override 338704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener, 339704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov int userId) { 340704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId); 341704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final UserState userState; 342704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov synchronized (mLock) { 343704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov userState = getOrCreateUserStateLocked(resolvedUserId); 344704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 345704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 346704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 347704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov userState.removePrintJobStateChangeListener(listener); 348704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } finally { 349704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Binder.restoreCallingIdentity(identity); 350704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 351704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 352704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 353704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov @Override 354b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 355b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 356b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov != PackageManager.PERMISSION_GRANTED) { 357b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov pw.println("Permission Denial: can't dump PrintManager from from pid=" 358b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov + Binder.getCallingPid() 359b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov + ", uid=" + Binder.getCallingUid()); 360b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov return; 361b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov } 362b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov 363b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov synchronized (mLock) { 3645fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav final long identity = Binder.clearCallingIdentity(); 3655fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav try { 3665fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav pw.println("PRINT MANAGER STATE (dumpsys print)"); 3675fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav final int userStateCount = mUserStates.size(); 3685fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav for (int i = 0; i < userStateCount; i++) { 3693cb2be97a226ae605f7b983739e02f40c0403989Svetoslav Ganov UserState userState = mUserStates.valueAt(i); 3705fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav userState.dump(fd, pw, ""); 3715fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav pw.println(); 3725fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav } 3735fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav } finally { 3745fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav Binder.restoreCallingIdentity(identity); 375b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov } 376b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov } 377b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov } 378b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov 3794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private void registerContentObservers() { 3804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final Uri enabledPrintServicesUri = Settings.Secure.getUriFor( 3814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Settings.Secure.ENABLED_PRINT_SERVICES); 3824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 383a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) { 3844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 3854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void onChange(boolean selfChange, Uri uri) { 3864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (enabledPrintServicesUri.equals(uri)) { 3874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 388a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov UserState userState = getCurrentUserStateLocked(); 389a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState.updateIfNeededLocked(); 3904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }; 3944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mContext.getContentResolver().registerContentObserver(enabledPrintServicesUri, 3964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov false, observer, UserHandle.USER_ALL); 3974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 399a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void registerBoradcastReceivers() { 4004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov PackageMonitor monitor = new PackageMonitor() { 4014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 402a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public boolean onPackageChanged(String packageName, int uid, String[] components) { 4034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 404a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov UserState userState = getOrCreateUserStateLocked(getChangingUserId()); 405a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Iterator<ComponentName> iterator = userState.getEnabledServices().iterator(); 406a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov while (iterator.hasNext()) { 407a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov ComponentName componentName = iterator.next(); 408a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (packageName.equals(componentName.getPackageName())) { 409a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState.updateIfNeededLocked(); 410a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return true; 411a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 4124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 414a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return false; 4154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 4174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 4184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void onPackageRemoved(String packageName, int uid) { 4194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 420a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov UserState userState = getOrCreateUserStateLocked(getChangingUserId()); 421a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Iterator<ComponentName> iterator = userState.getEnabledServices().iterator(); 4224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov while (iterator.hasNext()) { 4234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov ComponentName componentName = iterator.next(); 4244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (packageName.equals(componentName.getPackageName())) { 4254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov iterator.remove(); 426a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov persistComponentNamesToSettingLocked( 427a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Settings.Secure.ENABLED_PRINT_SERVICES, 428a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState.getEnabledServices(), getChangingUserId()); 429a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState.updateIfNeededLocked(); 4304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return; 4314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 4364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 4374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public boolean onHandleForceStop(Intent intent, String[] stoppedPackages, 4384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov int uid, boolean doit) { 4394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 440a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov UserState userState = getOrCreateUserStateLocked(getChangingUserId()); 441a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov boolean stoppedSomePackages = false; 442a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Iterator<ComponentName> iterator = userState.getEnabledServices().iterator(); 4434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov while (iterator.hasNext()) { 4444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov ComponentName componentName = iterator.next(); 4454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov String componentPackage = componentName.getPackageName(); 4464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov for (String stoppedPackage : stoppedPackages) { 4474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (componentPackage.equals(stoppedPackage)) { 4484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (!doit) { 4494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return true; 4504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 451a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov stoppedSomePackages = true; 452a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov break; 4534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 456a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (stoppedSomePackages) { 457a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState.updateIfNeededLocked(); 458a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 4594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return false; 4604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 463d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav @Override 464d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav public void onPackageAdded(String packageName, int uid) { 465d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE); 466d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav intent.setPackage(packageName); 467d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 468d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav List<ResolveInfo> installedServices = mContext.getPackageManager() 469d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .queryIntentServicesAsUser(intent, PackageManager.GET_SERVICES, 470d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav getChangingUserId()); 471d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 472cb247866acf10b039e02b600f8471b4a508f0ce8Svetoslav Ganov if (installedServices == null) { 473cb247866acf10b039e02b600f8471b4a508f0ce8Svetoslav Ganov return; 474cb247866acf10b039e02b600f8471b4a508f0ce8Svetoslav Ganov } 475cb247866acf10b039e02b600f8471b4a508f0ce8Svetoslav Ganov 476d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav final int installedServiceCount = installedServices.size(); 477d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav for (int i = 0; i < installedServiceCount; i++) { 478d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav ServiceInfo serviceInfo = installedServices.get(i).serviceInfo; 479d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav ComponentName component = new ComponentName(serviceInfo.packageName, 480d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav serviceInfo.name); 481d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav String label = serviceInfo.loadLabel(mContext.getPackageManager()).toString(); 4824a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov showEnableInstalledPrintServiceNotification(component, label, 4834a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov getChangingUserId()); 484d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav } 485d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav } 486d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 487a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void persistComponentNamesToSettingLocked(String settingName, 488a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Set<ComponentName> componentNames, int userId) { 489a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov StringBuilder builder = new StringBuilder(); 490a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov for (ComponentName componentName : componentNames) { 491a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (builder.length() > 0) { 492a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov builder.append(COMPONENT_NAME_SEPARATOR); 493a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 494a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov builder.append(componentName.flattenToShortString()); 495a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 496a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Settings.Secure.putStringForUser(mContext.getContentResolver(), 497a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov settingName, builder.toString(), userId); 4984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }; 5004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov // package changes 502a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov monitor.register(mContext, BackgroundThread.getHandler().getLooper(), 503a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov UserHandle.ALL, true); 5044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov // user changes 5064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov IntentFilter intentFilter = new IntentFilter(); 5074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 5082fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav intentFilter.addAction(Intent.ACTION_USER_REMOVED); 5094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mContext.registerReceiverAsUser(new BroadcastReceiver() { 5114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 5124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void onReceive(Context context, Intent intent) { 5134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov String action = intent.getAction(); 5144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (Intent.ACTION_USER_SWITCHED.equals(action)) { 5154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 516a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 517a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 5184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 520a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov }, UserHandle.ALL, intentFilter, null, BackgroundThread.getHandler()); 5214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 523a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private UserState getCurrentUserStateLocked() { 524a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return getOrCreateUserStateLocked(mCurrentUserId); 5254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 527a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private UserState getOrCreateUserStateLocked(int userId) { 528a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov UserState userState = mUserStates.get(userId); 529a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (userState == null) { 530a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState = new UserState(mContext, userId, mLock); 531a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mUserStates.put(userId, userState); 5324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 533a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return userState; 5344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private void switchUser(int newUserId) { 5372fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav UserState userState; 5384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 539a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (newUserId == mCurrentUserId) { 540a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return; 541a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 5424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mCurrentUserId = newUserId; 5432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState = mUserStates.get(mCurrentUserId); 5442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (userState == null) { 5452fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState = getCurrentUserStateLocked(); 5462fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState.updateIfNeededLocked(); 5472fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } else { 5482fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState.updateIfNeededLocked(); 5492fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 5504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav // This is the first time we switch to this user after boot, so 5522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav // now is the time to remove obsolete print jobs since they 5532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav // are from the last boot and no application would query them. 5542fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav userState.removeObsoletePrintJobs(); 5554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 557a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void removeUser(int removedUserId) { 5584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 559a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov UserState userState = mUserStates.get(removedUserId); 560a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (userState != null) { 561a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov userState.destroyLocked(); 562a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mUserStates.remove(removedUserId); 5634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 565a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 566a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 567a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private int resolveCallingAppEnforcingPermissions(int appId) { 568a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int callingUid = Binder.getCallingUid(); 569a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (callingUid == 0 || callingUid == Process.SYSTEM_UID 570a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov || callingUid == Process.SHELL_UID) { 571a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return appId; 5724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 573a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int callingAppId = UserHandle.getAppId(callingUid); 574a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (appId == callingAppId) { 575a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return appId; 576a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 577d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov if (mContext.checkCallingPermission( 578d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS") 579a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov != PackageManager.PERMISSION_GRANTED) { 580a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throw new SecurityException("Call from app " + callingAppId + " as app " 581d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov + appId + " without com.android.printspooler.permission" 582d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov + ".ACCESS_ALL_PRINT_JOBS"); 5834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 584a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return appId; 5854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 587a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private int resolveCallingUserEnforcingPermissions(int userId) { 5884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final int callingUid = Binder.getCallingUid(); 5894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (callingUid == 0 || callingUid == Process.SYSTEM_UID 5904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov || callingUid == Process.SHELL_UID) { 5914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return userId; 5924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final int callingUserId = UserHandle.getUserId(callingUid); 5944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (callingUserId == userId) { 5954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return userId; 5964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL) 5984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov != PackageManager.PERMISSION_GRANTED 5994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov || mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS) 6004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov != PackageManager.PERMISSION_GRANTED) { 6014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (userId == UserHandle.USER_CURRENT_OR_SELF) { 6024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return callingUserId; 6034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 6044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new SecurityException("Call from user " + callingUserId + " as user " 605a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov + userId + " without permission INTERACT_ACROSS_USERS or " 606a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov + "INTERACT_ACROSS_USERS_FULL not allowed."); 6074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 6084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF) { 6094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return mCurrentUserId; 6104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 6114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new IllegalArgumentException("Calling user can be changed to only " 6124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF."); 6134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 614d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 6157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav private String resolveCallingPackageNameEnforcingSecurity(String packageName) { 6167bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav if (TextUtils.isEmpty(packageName)) { 6177bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return null; 6187bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 6197bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav String[] packages = mContext.getPackageManager().getPackagesForUid( 6207bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Binder.getCallingUid()); 6217bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav final int packageCount = packages.length; 6227bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav for (int i = 0; i < packageCount; i++) { 6237bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav if (packageName.equals(packages[i])) { 6247bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return packageName; 6257bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 6267bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 6277bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return null; 6287bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 6297bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 630d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav private void showEnableInstalledPrintServiceNotification(ComponentName component, 6314a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov String label, int userId) { 6324a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov UserHandle userHandle = new UserHandle(userId); 6334a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov 634d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS); 635d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav intent.putExtra(EXTRA_PRINT_SERVICE_COMPONENT_NAME, component.flattenToString()); 636d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 6374a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext, 0, intent, 6384a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT, null, userHandle); 639d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 640d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav Notification.Builder builder = new Notification.Builder(mContext) 641d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .setSmallIcon(R.drawable.ic_print) 642d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .setContentTitle(mContext.getString(R.string.print_service_installed_title, label)) 643d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .setContentText(mContext.getString(R.string.print_service_installed_message)) 644d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .setContentIntent(pendingIntent) 645d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .setWhen(System.currentTimeMillis()) 646d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .setAutoCancel(true) 647d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .setShowWhen(true); 648d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 649d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav NotificationManager notificationManager = (NotificationManager) mContext 650d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav .getSystemService(Context.NOTIFICATION_SERVICE); 651d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav 652d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav String notificationTag = getClass().getName() + ":" + component.flattenToString(); 6534a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov notificationManager.notifyAsUser(notificationTag, 0, builder.build(), 6544a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov userHandle); 655d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav } 6564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 657