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
This commit is contained in:
Svetoslav
2014-05-08 12:48:23 -07:00
committed by Svetoslav Ganov
parent b09506dad9
commit 04533dd3ba

View File

@@ -28,6 +28,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
@@ -35,6 +36,7 @@ import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintJobStateChangeListener;
import android.print.IPrintManager;
@@ -91,18 +93,23 @@ public final class PrintManagerService extends SystemService {
private static final String 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 Context mContext;
private final UserManager mUserManager;
private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
private int mCurrentUserId = UserHandle.USER_OWNER;
PrintManagerImpl(Context context) {
mContext = context;
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
registerContentObservers();
registerBoradcastReceivers();
registerBroadcastReceivers();
}
public void systemRunning() {
@@ -125,11 +132,17 @@ public final class PrintManagerService extends SystemService {
@Override
public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
PrintAttributes attributes, String packageName, int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
String resolvedPackageName = resolveCallingPackageNameEnforcingSecurity(packageName);
final int resolvedAppId;
final UserState userState;
final String resolvedPackageName;
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);
}
final long identity = Binder.clearCallingIdentity();
@@ -143,10 +156,15 @@ public final class PrintManagerService extends SystemService {
@Override
public List<PrintJobInfo> getPrintJobInfos(int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final int resolvedAppId;
final UserState userState;
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);
}
final long identity = Binder.clearCallingIdentity();
@@ -159,10 +177,15 @@ public final class PrintManagerService extends SystemService {
@Override
public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final int resolvedAppId;
final UserState userState;
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);
}
final long identity = Binder.clearCallingIdentity();
@@ -175,10 +198,15 @@ public final class PrintManagerService extends SystemService {
@Override
public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final int resolvedAppId;
final UserState userState;
synchronized (mLock) {
// Only the current group members can cancel a print job.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -191,10 +219,15 @@ public final class PrintManagerService extends SystemService {
@Override
public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final int resolvedAppId;
final UserState userState;
synchronized (mLock) {
// Only the current group members can restart a print job.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -210,6 +243,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can get enabled services.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return null;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -225,6 +262,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can get installed services.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return null;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -241,6 +282,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can create a discovery session.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -257,6 +302,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can destroy a discovery session.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -273,6 +322,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can start discovery.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -288,6 +341,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can stop discovery.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -303,6 +360,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can validate printers.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -318,6 +379,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can start printer tracking.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -333,6 +398,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can stop printer tracking.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -347,9 +416,14 @@ public final class PrintManagerService extends SystemService {
public void addPrintJobStateChangeListener(IPrintJobStateChangeListener listener,
int appId, int userId) throws RemoteException {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedAppId;
final UserState userState;
synchronized (mLock) {
// Only the current group members can add a print job listener.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -366,6 +440,10 @@ public final class PrintManagerService extends SystemService {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
// Only the current group members can remove a print job listener.
if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) {
return;
}
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
@@ -421,11 +499,14 @@ public final class PrintManagerService extends SystemService {
false, observer, UserHandle.USER_ALL);
}
private void registerBoradcastReceivers() {
private void registerBroadcastReceivers() {
PackageMonitor monitor = new PackageMonitor() {
@Override
public void onPackageModified(String packageName) {
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;
UserState userState = getOrCreateUserStateLocked(getChangingUserId());
Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
@@ -444,6 +525,9 @@ public final class PrintManagerService extends SystemService {
@Override
public void onPackageRemoved(String packageName, int uid) {
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;
UserState userState = getOrCreateUserStateLocked(getChangingUserId());
Iterator<ComponentName> iterator = userState.getEnabledServices().iterator();
@@ -467,6 +551,9 @@ public final class PrintManagerService extends SystemService {
public boolean onHandleForceStop(Intent intent, String[] stoppedPackages,
int uid, boolean doit) {
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());
boolean stoppedSomePackages = false;
Iterator<ComponentName> iterator = userState.getEnabledServices()
@@ -493,6 +580,9 @@ public final class PrintManagerService extends SystemService {
@Override
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.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) {
final int callingUid = Binder.getCallingUid();
if (callingUid == 0 || callingUid == Process.SYSTEM_UID