Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04533dd3 authored by Svetoslav's avatar Svetoslav Committed by Svetoslav Ganov
Browse files

Teach print manager services about user profiles.

For user profiles the printing layer will have a separate state and
set a set of print plugins. The rationale behind this is that if a user
uses different profiles for different domains he would expect that
each domain is separate as domains may have different security and
privacy requirements.

bug:14567366

Change-Id: I461ae4636294fa8968785295afb952aeb14a13b5
parent b09506da
Loading
Loading
Loading
Loading
+116 −9
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.database.ContentObserver;
import android.net.Uri;
import android.net.Uri;
import android.os.Binder;
import android.os.Binder;
@@ -35,6 +36,7 @@ import android.os.Bundle;
import android.os.Process;
import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintJobStateChangeListener;
import android.print.IPrintJobStateChangeListener;
import android.print.IPrintManager;
import android.print.IPrintManager;
@@ -91,18 +93,23 @@ public final class PrintManagerService extends SystemService {
        private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
        private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
                "EXTRA_PRINT_SERVICE_COMPONENT_NAME";
                "EXTRA_PRINT_SERVICE_COMPONENT_NAME";


        private static final int BACKGROUND_USER_ID = -10;

        private final Object mLock = new Object();
        private final Object mLock = new Object();


        private final Context mContext;
        private final Context mContext;


        private final UserManager mUserManager;

        private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
        private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();


        private int mCurrentUserId = UserHandle.USER_OWNER;
        private int mCurrentUserId = UserHandle.USER_OWNER;


        PrintManagerImpl(Context context) {
        PrintManagerImpl(Context context) {
            mContext = context;
            mContext = context;
            mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
            registerContentObservers();
            registerContentObservers();
            registerBoradcastReceivers();
            registerBroadcastReceivers();
        }
        }


        public void systemRunning() {
        public void systemRunning() {
@@ -125,11 +132,17 @@ public final class PrintManagerService extends SystemService {
        @Override
        @Override
        public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
        public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
                PrintAttributes attributes, String packageName, int appId, int userId) {
                PrintAttributes attributes, String packageName, int appId, int userId) {
            final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            String resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName);
            final int resolvedAppId;
            final UserState userState;
            final UserState userState;
            final String resolvedPackageName;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can start new print jobs.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return null;
                }
                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
                resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName);
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -143,10 +156,15 @@ public final class PrintManagerService extends SystemService {


        @Override
        @Override
        public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) {
        public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) {
            final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedAppId;
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can query for state of print jobs.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return null;
                }
                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -159,10 +177,15 @@ public final class PrintManagerService extends SystemService {


        @Override
        @Override
        public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) {
        public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) {
            final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedAppId;
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can query for state of a print job.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return null;
                }
                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -175,10 +198,15 @@ public final class PrintManagerService extends SystemService {


        @Override
        @Override
        public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) {
        public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) {
            final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedAppId;
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can cancel a print job.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -191,10 +219,15 @@ public final class PrintManagerService extends SystemService {


        @Override
        @Override
        public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
        public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
            final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedAppId;
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can restart a print job.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -210,6 +243,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can get enabled services.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return null;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -225,6 +262,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can get installed services.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return null;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -241,6 +282,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can create a discovery session.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -257,6 +302,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can destroy a discovery session.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -273,6 +322,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can start discovery.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -288,6 +341,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can stop discovery.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -303,6 +360,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can validate printers.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -318,6 +379,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can start printer tracking.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -333,6 +398,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can stop printer tracking.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -347,9 +416,14 @@ public final class PrintManagerService extends SystemService {
        public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
        public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
                int appId, int userId) throws RemoteException {
                int appId, int userId) throws RemoteException {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
            final int resolvedAppId;
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can add a print job listener.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -366,6 +440,10 @@ public final class PrintManagerService extends SystemService {
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
            final UserState userState;
            final UserState userState;
            synchronized (mLock) {
            synchronized (mLock) {
                // Only the current group members can remove a print job listener.
                if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
                    return;
                }
                userState = getOrCreateUserStateLocked(resolvedUserId);
                userState = getOrCreateUserStateLocked(resolvedUserId);
            }
            }
            final long identity = Binder.clearCallingIdentity();
            final long identity = Binder.clearCallingIdentity();
@@ -421,11 +499,14 @@ public final class PrintManagerService extends SystemService {
                    false, observer, UserHandle.USER_ALL);
                    false, observer, UserHandle.USER_ALL);
        }
        }


        private void registerBoradcastReceivers() {
        private void registerBroadcastReceivers() {
            PackageMonitor monitor = new PackageMonitor() {
            PackageMonitor monitor = new PackageMonitor() {
                @Override
                @Override
                public void onPackageModified(String packageName) {
                public void onPackageModified(String packageName) {
                    synchronized (mLock) {
                    synchronized (mLock) {
                        // A background user/profile's print jobs are running but there is
                        // no UI shown. Hence, if the packages of such a user change we need
                        // to handle it as the change may affect ongoing print jobs.
                        boolean servicesChanged = false;
                        boolean servicesChanged = false;
                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
                        Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
                        Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
@@ -444,6 +525,9 @@ public final class PrintManagerService extends SystemService {
                @Override
                @Override
                public void onPackageRemoved(String packageName, int uid) {
                public void onPackageRemoved(String packageName, int uid) {
                    synchronized (mLock) {
                    synchronized (mLock) {
                        // A background user/profile's print jobs are running but there is
                        // no UI shown. Hence, if the packages of such a user change we need
                        // to handle it as the change may affect ongoing print jobs.
                        boolean servicesRemoved = false;
                        boolean servicesRemoved = false;
                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
                        Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
                        Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
@@ -467,6 +551,9 @@ public final class PrintManagerService extends SystemService {
                public boolean onHandleForceStop(Intent intent, String[] stoppedPackages,
                public boolean onHandleForceStop(Intent intent, String[] stoppedPackages,
                        int uid, boolean doit) {
                        int uid, boolean doit) {
                    synchronized (mLock) {
                    synchronized (mLock) {
                        // A background user/profile's print jobs are running but there is
                        // no UI shown. Hence, if the packages of such a user change we need
                        // to handle it as the change may affect ongoing print jobs.
                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
                        UserState userState = getOrCreateUserStateLocked(getChangingUserId());
                        boolean stoppedSomePackages = false;
                        boolean stoppedSomePackages = false;
                        Iterator<ComponentName> iterator = userState.getEnabledServices()
                        Iterator<ComponentName> iterator = userState.getEnabledServices()
@@ -493,6 +580,9 @@ public final class PrintManagerService extends SystemService {


                @Override
                @Override
                public void onPackageAdded(String packageName, int uid) {
                public void onPackageAdded(String packageName, int uid) {
                    // A background user/profile's print jobs are running but there is
                    // no UI shown. Hence, if the packages of such a user change we need
                    // to handle it as the change may affect ongoing print jobs.
                    Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
                    Intent intent = new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
                    intent.setPackage(packageName);
                    intent.setPackage(packageName);


@@ -596,6 +686,23 @@ public final class PrintManagerService extends SystemService {
            }
            }
        }
        }


        private int resolveCallingProfileParentLocked(int userId) {
            if (userId != mCurrentUserId) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    UserInfo parent = mUserManager.getProfileParent(userId);
                    if (parent != null) {
                        return parent.getUserHandle().getIdentifier();
                    } else {
                        return BACKGROUND_USER_ID;
                    }
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
            return userId;
        }

        private int resolveCallingAppEnforcingPermissions(int appId) {
        private int resolveCallingAppEnforcingPermissions(int appId) {
            final int callingUid = Binder.getCallingUid();
            final int callingUid = Binder.getCallingUid();
            if (callingUid == 0 || callingUid == Process.SYSTEM_UID
            if (callingUid == 0 || callingUid == Process.SYSTEM_UID