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;
2086b1df234397802895771fe14cd8f2813fa43415Svetoslavimport android.app.ActivityManager;
2186b1df234397802895771fe14cd8f2813fa43415Svetoslavimport android.app.ActivityManagerNative;
22d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.app.Notification;
23d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.app.NotificationManager;
24d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.app.PendingIntent;
254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.ComponentName;
264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Context;
274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Intent;
284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.pm.PackageManager;
2907ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guyimport android.content.pm.PackageManager.NameNotFoundException;
30d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.content.pm.ResolveInfo;
31d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport android.content.pm.ServiceInfo;
3204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslavimport android.content.pm.UserInfo;
334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.database.ContentObserver;
344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.net.Uri;
354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Binder;
367bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslavimport android.os.Bundle;
374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Process;
38704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport android.os.RemoteException;
394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.UserHandle;
4004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslavimport android.os.UserManager;
41a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintDocumentAdapter;
42704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport android.print.IPrintJobStateChangeListener;
434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.IPrintManager;
4444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganovimport android.print.IPrinterDiscoveryObserver;
454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes;
462fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport android.print.PrintJobId;
474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintJobInfo;
4844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganovimport android.print.PrinterId;
49860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganovimport android.printservice.PrintServiceInfo;
504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.provider.Settings;
517bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslavimport android.text.TextUtils;
52a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.util.SparseArray;
534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
54d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslavimport com.android.internal.R;
554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.internal.content.PackageMonitor;
56a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport com.android.internal.os.BackgroundThread;
57817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasaniimport com.android.server.SystemService;
584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
59b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.FileDescriptor;
60b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.PrintWriter;
614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Iterator;
624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List;
634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Set;
644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
65817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani/**
66817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani * SystemService wrapper for the PrintManager implementation. Publishes
67817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani * Context.PRINT_SERVICE.
68817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani * PrintManager implementation is contained within.
69817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani */
704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
71817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasanipublic final class PrintManagerService extends SystemService {
72b880d880c6cd989eacc28c365fc9a41d31900da1Jeff Brown    private final PrintManagerImpl mPrintManagerImpl;
734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
74b880d880c6cd989eacc28c365fc9a41d31900da1Jeff Brown    public PrintManagerService(Context context) {
75b880d880c6cd989eacc28c365fc9a41d31900da1Jeff Brown        super(context);
76817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        mPrintManagerImpl = new PrintManagerImpl(context);
774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
78b880d880c6cd989eacc28c365fc9a41d31900da1Jeff Brown
794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
80817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani    public void onStart() {
81817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        publishBinderService(Context.PRINT_SERVICE, mPrintManagerImpl);
824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
8586b1df234397802895771fe14cd8f2813fa43415Svetoslav    public void onStartUser(int userHandle) {
8686b1df234397802895771fe14cd8f2813fa43415Svetoslav        mPrintManagerImpl.handleUserStarted(userHandle);
8786b1df234397802895771fe14cd8f2813fa43415Svetoslav    }
8886b1df234397802895771fe14cd8f2813fa43415Svetoslav
8986b1df234397802895771fe14cd8f2813fa43415Svetoslav    @Override
9086b1df234397802895771fe14cd8f2813fa43415Svetoslav    public void onStopUser(int userHandle) {
9186b1df234397802895771fe14cd8f2813fa43415Svetoslav        mPrintManagerImpl.handleUserStopped(userHandle);
924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
94817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani    class PrintManagerImpl extends IPrintManager.Stub {
95817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private static final char COMPONENT_NAME_SEPARATOR = ':';
968c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov
97817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
98817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                "EXTRA_PRINT_SERVICE_COMPONENT_NAME";
994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
10004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav        private static final int BACKGROUND_USER_ID = -10;
10104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav
102817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private final Object mLock = new Object();
103860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov
104817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private final Context mContext;
105d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav
10604533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav        private final UserManager mUserManager;
10704533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav
10886b1df234397802895771fe14cd8f2813fa43415Svetoslav        private final SparseArray<UserState> mUserStates = new SparseArray<>();
109817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
110817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        PrintManagerImpl(Context context) {
111817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            mContext = context;
11204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
113817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            registerContentObservers();
11404533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            registerBroadcastReceivers();
11544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov        }
11644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov
117817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
118817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
119817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                PrintAttributes attributes, String packageName, int appId, int userId) {
120817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
12104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            final int resolvedAppId;
122817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
12304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            final String resolvedPackageName;
124817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
12504533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can start new print jobs.
12686b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
12704533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return null;
12804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
12904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
13004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName);
131817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
132817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
133817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
134817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
135817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return userState.print(printJobName, adapter, attributes,
136817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        resolvedPackageName, resolvedAppId);
137817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
138817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
139817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
14044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov        }
141817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
142817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
143817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) {
144817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
14504533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            final int resolvedAppId;
146817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
147817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
14804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can query for state of print jobs.
14986b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
15004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return null;
15104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
15204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
153817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
154817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
155817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
156817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
157817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return userState.getPrintJobInfos(resolvedAppId);
158817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
159817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
160817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
16144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov        }
16244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov
163817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
164817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) {
165817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
16604533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            final int resolvedAppId;
167817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
168817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
16904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can query for state of a print job.
17086b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
17104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return null;
17204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
17304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
174817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
175817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
176817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
177817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
178817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return userState.getPrintJobInfo(printJobId, resolvedAppId);
179817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
180817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
181817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
18244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov        }
183817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
184817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
185817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) {
186817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
18704533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            final int resolvedAppId;
188817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
189817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
19004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can cancel a print job.
19186b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
19204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
19304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
19404533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
195817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
196817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
197817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
198817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
199817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.cancelPrintJob(printJobId, resolvedAppId);
200817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
201817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
202817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
20344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov        }
20444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov
205817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
206817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
207817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
20804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            final int resolvedAppId;
209817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
210817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
21104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can restart a print job.
21286b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
21304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
21404533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
21504533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
216817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
217817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
218817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
219817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
220817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.restartPrintJob(printJobId, resolvedAppId);
221817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
222817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
223817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
22444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov        }
225817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
226817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
227817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public List<PrintServiceInfo> getEnabledPrintServices(int userId) {
228817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
229817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
230817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
23104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can get enabled services.
23286b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
23304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return null;
23404533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
235817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
236817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
237817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
238817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
239817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return userState.getEnabledPrintServices();
240817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
241817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
242817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
243d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        }
244d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov
245817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
246817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public List<PrintServiceInfo> getInstalledPrintServices(int userId) {
247817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
248817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
249817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
25004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can get installed services.
25186b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
25204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return null;
25304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
254817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
255817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
256817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
257817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
258817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return userState.getInstalledPrintServices();
259817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
260817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
261817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
262d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        }
263817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
264817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
265817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void createPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
266817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                int userId) {
267817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
268817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
269817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
27004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can create a discovery session.
27186b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
27204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
27304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
274817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
275817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
276817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
277817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
278817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.createPrinterDiscoverySession(observer);
279817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
280817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
281817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
282d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        }
283d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov
284817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
285817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void destroyPrinterDiscoverySession(IPrinterDiscoveryObserver observer,
286817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                int userId) {
287817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
288817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
289817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
29004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can destroy a discovery session.
29186b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
29204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
29304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
294817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
295817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
296817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
297817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
298817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.destroyPrinterDiscoverySession(observer);
299817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
300817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
301817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
302d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        }
303817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
304817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
305817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void startPrinterDiscovery(IPrinterDiscoveryObserver observer,
306817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                List<PrinterId> priorityList, int userId) {
307817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
308817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
309817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
31004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can start discovery.
31186b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
31204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
31304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
314817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
315817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
316817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
317817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
318817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.startPrinterDiscovery(observer, priorityList);
319817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
320817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
321817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
32244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov        }
32344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov
324817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
325817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void stopPrinterDiscovery(IPrinterDiscoveryObserver observer, int userId) {
326817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
327817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
328817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
32904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can stop discovery.
33086b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
33104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
33204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
333817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
334817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
335817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
336817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
337817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.stopPrinterDiscovery(observer);
338817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
339817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
340817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
341704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
342817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
343817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
344817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void validatePrinters(List<PrinterId> printerIds, int userId) {
345817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
346817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
347817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
34804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can validate printers.
34986b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
35004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
35104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
352817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
353817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
354817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
355817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
356817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.validatePrinters(printerIds);
357817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
358817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
359817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
360704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
361704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
362817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
363817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void startPrinterStateTracking(PrinterId printerId, int userId) {
364817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
365817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
366817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
36704533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can start printer tracking.
36886b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
36904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
37004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
371817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
372817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
373817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
374817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
375817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.startPrinterStateTracking(printerId);
376817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
377817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
378817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
379704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
380817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
381817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
382817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void stopPrinterStateTracking(PrinterId printerId, int userId) {
383817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
384817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
385817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
38604533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can stop printer tracking.
38786b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
38804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
38904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
390817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
391817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
392817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
393817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
394817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.stopPrinterStateTracking(printerId);
395817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
396817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
397817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
398704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
399704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
400817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
401817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
402817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                int appId, int userId) throws RemoteException {
403817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
40404533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            final int resolvedAppId;
405817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
406817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
40704533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can add a print job listener.
40886b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
40904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
41004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
41104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
412817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
413817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
414817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final long identity = Binder.clearCallingIdentity();
415817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            try {
416817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.addPrintJobStateChangeListener(listener, resolvedAppId);
417817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            } finally {
418817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                Binder.restoreCallingIdentity(identity);
419817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
420b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov        }
421b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov
422817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
423817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void removePrintJobStateChangeListener(IPrintJobStateChangeListener listener,
424817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                int userId) {
425817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
426817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final UserState userState;
427817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
42804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                // Only the current group members can remove a print job listener.
42986b1df234397802895771fe14cd8f2813fa43415Svetoslav                if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) {
43004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    return;
43104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
432817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = getOrCreateUserStateLocked(resolvedUserId);
433817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
4345fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav            final long identity = Binder.clearCallingIdentity();
4355fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav            try {
436817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState.removePrintJobStateChangeListener(listener);
4375fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav            } finally {
4385fe07aa7a81c840eaf52bf95d4d5bacd914a8106Svetoslav                Binder.restoreCallingIdentity(identity);
439b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov            }
440b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov        }
441b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov
442817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        @Override
443817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
444817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
445817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    != PackageManager.PERMISSION_GRANTED) {
446817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                pw.println("Permission Denial: can't dump PrintManager from from pid="
447817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        + Binder.getCallingPid()
448817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        + ", uid=" + Binder.getCallingUid());
449817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return;
450817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
4514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
452817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            synchronized (mLock) {
453817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                final long identity = Binder.clearCallingIdentity();
454817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                try {
455817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    pw.println("PRINT MANAGER STATE (dumpsys print)");
456817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    final int userStateCount = mUserStates.size();
457817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    for (int i = 0; i < userStateCount; i++) {
458817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        UserState userState = mUserStates.valueAt(i);
459817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        userState.dump(fd, pw, "");
460817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        pw.println();
4614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
462817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                } finally {
463817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    Binder.restoreCallingIdentity(identity);
4644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
4654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
466817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        }
4674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
468817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private void registerContentObservers() {
469817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final Uri enabledPrintServicesUri = Settings.Secure.getUriFor(
470817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    Settings.Secure.ENABLED_PRINT_SERVICES);
471817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) {
472817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                @Override
47386b1df234397802895771fe14cd8f2813fa43415Svetoslav                public void onChange(boolean selfChange, Uri uri, int userId) {
474817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    if (enabledPrintServicesUri.equals(uri)) {
475817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        synchronized (mLock) {
47686b1df234397802895771fe14cd8f2813fa43415Svetoslav                            if (userId != UserHandle.USER_ALL) {
47786b1df234397802895771fe14cd8f2813fa43415Svetoslav                                UserState userState = getOrCreateUserStateLocked(userId);
47886b1df234397802895771fe14cd8f2813fa43415Svetoslav                                userState.updateIfNeededLocked();
47986b1df234397802895771fe14cd8f2813fa43415Svetoslav                            } else {
48086b1df234397802895771fe14cd8f2813fa43415Svetoslav                                final int userCount = mUserStates.size();
48186b1df234397802895771fe14cd8f2813fa43415Svetoslav                                for (int i = 0; i < userCount; i++) {
48286b1df234397802895771fe14cd8f2813fa43415Svetoslav                                    UserState userState = mUserStates.valueAt(i);
48386b1df234397802895771fe14cd8f2813fa43415Svetoslav                                    userState.updateIfNeededLocked();
48486b1df234397802895771fe14cd8f2813fa43415Svetoslav                                }
48586b1df234397802895771fe14cd8f2813fa43415Svetoslav                            }
486a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                        }
4874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
4884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
489817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            };
4904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
491817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            mContext.getContentResolver().registerContentObserver(enabledPrintServicesUri,
492817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    false, observer, UserHandle.USER_ALL);
493817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        }
494817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
49504533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav        private void registerBroadcastReceivers() {
496817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            PackageMonitor monitor = new PackageMonitor() {
497817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                @Override
498e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                public void onPackageModified(String packageName) {
499817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    synchronized (mLock) {
50004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // A background user/profile's print jobs are running but there is
50104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // no UI shown. Hence, if the packages of such a user change we need
50204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // to handle it as the change may affect ongoing print jobs.
503e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                        boolean servicesChanged = false;
504817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
505e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                        Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
506817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        while (iterator.hasNext()) {
507817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            ComponentName componentName = iterator.next();
508817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            if (packageName.equals(componentName.getPackageName())) {
509e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                                servicesChanged = true;
510817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            }
5114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        }
512e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                        if (servicesChanged) {
513e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                            userState.updateIfNeededLocked();
5144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        }
5154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
5164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
5174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
518817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                @Override
519817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                public void onPackageRemoved(String packageName, int uid) {
520817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    synchronized (mLock) {
52104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // A background user/profile's print jobs are running but there is
52204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // no UI shown. Hence, if the packages of such a user change we need
52304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // to handle it as the change may affect ongoing print jobs.
524e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                        boolean servicesRemoved = false;
525817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
526e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                        Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
527817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        while (iterator.hasNext()) {
528817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            ComponentName componentName = iterator.next();
529817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            if (packageName.equals(componentName.getPackageName())) {
530817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                iterator.remove();
531e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                                servicesRemoved = true;
5324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                            }
5334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        }
534e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                        if (servicesRemoved) {
535e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                            persistComponentNamesToSettingLocked(
536e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                                    Settings.Secure.ENABLED_PRINT_SERVICES,
537e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                                    userState.getEnabledServices(), getChangingUserId());
538e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                            userState.updateIfNeededLocked();
539e58a49e411327e26b6ad9939833f53c7fa5aef20Amith Yamasani                        }
540dbcc95d4d889c4de2490870cfeb97cc8f6deb30eSvetoslav                    }
5414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
5424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
543817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                @Override
544817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                public boolean onHandleForceStop(Intent intent, String[] stoppedPackages,
545817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        int uid, boolean doit) {
546817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    synchronized (mLock) {
54704533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // A background user/profile's print jobs are running but there is
54804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // no UI shown. Hence, if the packages of such a user change we need
54904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        // to handle it as the change may affect ongoing print jobs.
550817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
551817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        boolean stoppedSomePackages = false;
552817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        Iterator<ComponentName> iterator = userState.getEnabledServices()
553817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                .iterator();
554817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        while (iterator.hasNext()) {
555817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            ComponentName componentName = iterator.next();
556817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            String componentPackage = componentName.getPackageName();
557817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            for (String stoppedPackage : stoppedPackages) {
558817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                if (componentPackage.equals(stoppedPackage)) {
559817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                    if (!doit) {
560817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                        return true;
561817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                    }
562817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                    stoppedSomePackages = true;
563817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                    break;
5644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                                }
5654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                            }
5664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        }
567817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        if (stoppedSomePackages) {
568817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            userState.updateIfNeededLocked();
569817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        }
570817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        return false;
5714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
5724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
5734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
574817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                @Override
575817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                public void onPackageAdded(String packageName, int uid) {
57604533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    // A background user/profile's print jobs are running but there is
57704533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    // no UI shown. Hence, if the packages of such a user change we need
57804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    // to handle it as the change may affect ongoing print jobs.
579817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
580817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    intent.setPackage(packageName);
581d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav
582817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    List<ResolveInfo> installedServices = mContext.getPackageManager()
583817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            .queryIntentServicesAsUser(intent, PackageManager.GET_SERVICES,
584817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                    getChangingUserId());
585d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav
586817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    if (installedServices == null) {
587817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        return;
588817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    }
589cb247866acf10b039e02b600f8471b4a508f0ce8Svetoslav Ganov
590817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    final int installedServiceCount = installedServices.size();
591817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    for (int i = 0; i < installedServiceCount; i++) {
592817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        ServiceInfo serviceInfo = installedServices.get(i).serviceInfo;
593817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        ComponentName component = new ComponentName(serviceInfo.packageName,
594817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                serviceInfo.name);
595817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        String label = serviceInfo.loadLabel(mContext.getPackageManager())
596817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                .toString();
597817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        showEnableInstalledPrintServiceNotification(component, label,
598817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                                getChangingUserId());
599817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    }
600d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav                }
601d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav
602817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                private void persistComponentNamesToSettingLocked(String settingName,
603817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        Set<ComponentName> componentNames, int userId) {
604817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    StringBuilder builder = new StringBuilder();
605817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    for (ComponentName componentName : componentNames) {
606817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        if (builder.length() > 0) {
607817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            builder.append(COMPONENT_NAME_SEPARATOR);
608817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        }
609817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        builder.append(componentName.flattenToShortString());
610a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    }
611817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
612817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            settingName, builder.toString(), userId);
613a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
614817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            };
615817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
616817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            // package changes
617817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            monitor.register(mContext, BackgroundThread.getHandler().getLooper(),
618817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    UserHandle.ALL, true);
6194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
6204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
621817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private UserState getOrCreateUserStateLocked(int userId) {
622817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            UserState userState = mUserStates.get(userId);
6232fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            if (userState == null) {
624817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                userState = new UserState(mContext, userId, mLock);
625817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                mUserStates.put(userId, userState);
6262fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            }
627817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            return userState;
6284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
6294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
630c82768ff4b045b5b4edc08405964d504438a681fSvetoslav        private void handleUserStarted(final int userId) {
631c82768ff4b045b5b4edc08405964d504438a681fSvetoslav            // This code will touch the remote print spooler which
632c82768ff4b045b5b4edc08405964d504438a681fSvetoslav            // must be called off the main thread, so post the work.
633c82768ff4b045b5b4edc08405964d504438a681fSvetoslav            BackgroundThread.getHandler().post(new Runnable() {
634c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                @Override
635c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                public void run() {
636c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    UserState userState;
637c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    synchronized (mLock) {
638c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                        userState = getOrCreateUserStateLocked(userId);
639c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                        userState.updateIfNeededLocked();
640c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    }
641c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    // This is the first time we switch to this user after boot, so
642c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    // now is the time to remove obsolete print jobs since they
643c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    // are from the last boot and no application would query them.
644c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    userState.removeObsoletePrintJobs();
645c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                }
646c82768ff4b045b5b4edc08405964d504438a681fSvetoslav            });
647817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        }
648817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani
649c82768ff4b045b5b4edc08405964d504438a681fSvetoslav        private void handleUserStopped(final int userId) {
650c82768ff4b045b5b4edc08405964d504438a681fSvetoslav            // This code will touch the remote print spooler which
651c82768ff4b045b5b4edc08405964d504438a681fSvetoslav            // must be called off the main thread, so post the work.
652c82768ff4b045b5b4edc08405964d504438a681fSvetoslav            BackgroundThread.getHandler().post(new Runnable() {
653c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                @Override
654c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                public void run() {
655c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    synchronized (mLock) {
656c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                        UserState userState = mUserStates.get(userId);
657c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                        if (userState != null) {
658c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                            userState.destroyLocked();
659c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                            mUserStates.remove(userId);
660c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                        }
661c82768ff4b045b5b4edc08405964d504438a681fSvetoslav                    }
662817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                }
663c82768ff4b045b5b4edc08405964d504438a681fSvetoslav            });
6644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
665a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
66604533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav        private int resolveCallingProfileParentLocked(int userId) {
66786b1df234397802895771fe14cd8f2813fa43415Svetoslav            if (userId != getCurrentUserId()) {
66804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                final long identity = Binder.clearCallingIdentity();
66904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                try {
67004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    UserInfo parent = mUserManager.getProfileParent(userId);
67104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    if (parent != null) {
67204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        return parent.getUserHandle().getIdentifier();
67304533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    } else {
67404533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                        return BACKGROUND_USER_ID;
67504533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    }
67604533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                } finally {
67704533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                    Binder.restoreCallingIdentity(identity);
67804533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav                }
67904533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            }
68004533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav            return userId;
68104533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav        }
68204533dd3ba4e916f5a639d0cfbc331c32515cc84Svetoslav
683817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private int resolveCallingAppEnforcingPermissions(int appId) {
684817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int callingUid = Binder.getCallingUid();
685817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            if (callingUid == 0 || callingUid == Process.SYSTEM_UID
686817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    || callingUid == Process.SHELL_UID) {
687817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return appId;
688817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
689817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int callingAppId = UserHandle.getAppId(callingUid);
690817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            if (appId == callingAppId) {
691817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return appId;
692817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
693817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            if (mContext.checkCallingPermission(
694817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS")
695817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    != PackageManager.PERMISSION_GRANTED) {
696817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                throw new SecurityException("Call from app " + callingAppId + " as app "
697817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        + appId + " without com.android.printspooler.permission"
698817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                        + ".ACCESS_ALL_PRINT_JOBS");
699817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
700a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return appId;
701a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
7024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
703817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private int resolveCallingUserEnforcingPermissions(int userId) {
70486b1df234397802895771fe14cd8f2813fa43415Svetoslav            try {
70586b1df234397802895771fe14cd8f2813fa43415Svetoslav                return ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
70686b1df234397802895771fe14cd8f2813fa43415Svetoslav                        Binder.getCallingUid(), userId, true, true, "", null);
70786b1df234397802895771fe14cd8f2813fa43415Svetoslav            } catch (RemoteException re) {
70886b1df234397802895771fe14cd8f2813fa43415Svetoslav                // Shouldn't happen, local.
709817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
710194db6ad91c4aee995930ea8f04ea877730234fdSvet Ganov            return userId;
7114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
712d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav
713817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private String resolveCallingPackageNameEnforcingSecurity(String packageName) {
714817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            if (TextUtils.isEmpty(packageName)) {
715817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                return null;
716817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            }
717817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            String[] packages = mContext.getPackageManager().getPackagesForUid(
718817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    Binder.getCallingUid());
719817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            final int packageCount = packages.length;
720817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            for (int i = 0; i < packageCount; i++) {
721817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                if (packageName.equals(packages[i])) {
722817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    return packageName;
723817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                }
7247bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            }
725817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            return null;
7267bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
7277bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
72886b1df234397802895771fe14cd8f2813fa43415Svetoslav        private int getCurrentUserId () {
72986b1df234397802895771fe14cd8f2813fa43415Svetoslav            final long identity = Binder.clearCallingIdentity();
73086b1df234397802895771fe14cd8f2813fa43415Svetoslav            try {
73186b1df234397802895771fe14cd8f2813fa43415Svetoslav                return ActivityManager.getCurrentUser();
73286b1df234397802895771fe14cd8f2813fa43415Svetoslav            } finally {
73386b1df234397802895771fe14cd8f2813fa43415Svetoslav                Binder.restoreCallingIdentity(identity);
73486b1df234397802895771fe14cd8f2813fa43415Svetoslav            }
73586b1df234397802895771fe14cd8f2813fa43415Svetoslav        }
73686b1df234397802895771fe14cd8f2813fa43415Svetoslav
737817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        private void showEnableInstalledPrintServiceNotification(ComponentName component,
738817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                String label, int userId) {
739817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            UserHandle userHandle = new UserHandle(userId);
7404a82b455f9832430207e3ecfddfad4b67b071407Svetoslav Ganov
741817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS);
742817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            intent.putExtra(EXTRA_PRINT_SERVICE_COMPONENT_NAME, component.flattenToString());
743d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav
744817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext, 0, intent,
745817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT, null,
746817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    userHandle);
747d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav
74807ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guy            Context builderContext = mContext;
74907ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guy            try {
75007ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guy                builderContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
75107ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guy                        userHandle);
75207ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guy            } catch (NameNotFoundException e) {
75307ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guy                // Ignore can't find the package the system is running as.
75407ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guy            }
75507ad8dc2087aa02da48353acc19ba82e62d99f82Kenny Guy            Notification.Builder builder = new Notification.Builder(builderContext)
756817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    .setSmallIcon(R.drawable.ic_print)
757817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    .setContentTitle(mContext.getString(R.string.print_service_installed_title,
758817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                            label))
759817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    .setContentText(mContext.getString(R.string.print_service_installed_message))
760817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    .setContentIntent(pendingIntent)
761817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    .setWhen(System.currentTimeMillis())
762817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    .setAutoCancel(true)
763255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek                    .setShowWhen(true)
7644a357cd2e55293402d7172766f7f9419815fc1e8Alan Viverette                    .setColor(mContext.getColor(
765255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek                            com.android.internal.R.color.system_notification_accent_color));
766d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav
767817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            NotificationManager notificationManager = (NotificationManager) mContext
768817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    .getSystemService(Context.NOTIFICATION_SERVICE);
769d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav
770817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            String notificationTag = getClass().getName() + ":" + component.flattenToString();
771817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani            notificationManager.notifyAsUser(notificationTag, 0, builder.build(),
772817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani                    userHandle);
773817ec49e7991d4cac50b2308cd7cf5f8641e1e29Amith Yamasani        }
774d8f391b4e0e8d876ec7216d34f86a9b3e8bab7e5Svetoslav    }
7754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov}
776