diff options
5 files changed, 114 insertions, 125 deletions
diff --git a/core/java/android/database/ContentObserver.java b/core/java/android/database/ContentObserver.java index e4fbc28..5f01e30 100644 --- a/core/java/android/database/ContentObserver.java +++ b/core/java/android/database/ContentObserver.java @@ -18,6 +18,7 @@ package android.database; import android.net.Uri; import android.os.Handler; +import android.os.UserHandle; /** * Receives call backs for changes to content. @@ -130,6 +131,21 @@ public abstract class ContentObserver { } /** + * Dispatches a change notification to the observer. Includes the changed + * content Uri when available and also the user whose content changed. + * + * @param selfChange True if this is a self-change notification. + * @param uri The Uri of the changed content, or null if unknown. + * @param userId The user whose content changed. Can be either a specific + * user or {@link UserHandle#USER_ALL}. + * + * @hide + */ + public void onChange(boolean selfChange, Uri uri, int userId) { + onChange(selfChange, uri); + } + + /** * Dispatches a change notification to the observer. * <p> * If a {@link Handler} was supplied to the {@link ContentObserver} constructor, @@ -159,25 +175,45 @@ public abstract class ContentObserver { * @param uri The Uri of the changed content, or null if unknown. */ public final void dispatchChange(boolean selfChange, Uri uri) { + dispatchChange(selfChange, uri, UserHandle.getCallingUserId()); + } + + /** + * Dispatches a change notification to the observer. Includes the changed + * content Uri when available and also the user whose content changed. + * <p> + * If a {@link Handler} was supplied to the {@link ContentObserver} constructor, + * then a call to the {@link #onChange} method is posted to the handler's message queue. + * Otherwise, the {@link #onChange} method is invoked immediately on this thread. + * </p> + * + * @param selfChange True if this is a self-change notification. + * @param uri The Uri of the changed content, or null if unknown. + * @param userId The user whose content changed. + */ + private void dispatchChange(boolean selfChange, Uri uri, int userId) { if (mHandler == null) { - onChange(selfChange, uri); + onChange(selfChange, uri, userId); } else { - mHandler.post(new NotificationRunnable(selfChange, uri)); + mHandler.post(new NotificationRunnable(selfChange, uri, userId)); } } + private final class NotificationRunnable implements Runnable { private final boolean mSelfChange; private final Uri mUri; + private final int mUserId; - public NotificationRunnable(boolean selfChange, Uri uri) { + public NotificationRunnable(boolean selfChange, Uri uri, int userId) { mSelfChange = selfChange; mUri = uri; + mUserId = userId; } @Override public void run() { - ContentObserver.this.onChange(mSelfChange, mUri); + ContentObserver.this.onChange(mSelfChange, mUri, mUserId); } } @@ -189,10 +225,10 @@ public abstract class ContentObserver { } @Override - public void onChange(boolean selfChange, Uri uri) { + public void onChange(boolean selfChange, Uri uri, int userId) { ContentObserver contentObserver = mContentObserver; if (contentObserver != null) { - contentObserver.dispatchChange(selfChange, uri); + contentObserver.dispatchChange(selfChange, uri, userId); } } diff --git a/core/java/android/database/CursorToBulkCursorAdaptor.java b/core/java/android/database/CursorToBulkCursorAdaptor.java index 7dcfae2..02eddf2 100644 --- a/core/java/android/database/CursorToBulkCursorAdaptor.java +++ b/core/java/android/database/CursorToBulkCursorAdaptor.java @@ -17,9 +17,7 @@ package android.database; import android.net.Uri; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; +import android.os.*; /** @@ -33,7 +31,7 @@ import android.os.RemoteException; * * {@hide} */ -public final class CursorToBulkCursorAdaptor extends BulkCursorNative +public final class CursorToBulkCursorAdaptor extends BulkCursorNative implements IBinder.DeathRecipient { private static final String TAG = "Cursor"; @@ -66,7 +64,7 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative // Do nothing, the far side is dead } } - + public boolean unlinkToDeath(DeathRecipient recipient) { return mRemote.asBinder().unlinkToDeath(recipient, 0); } @@ -80,7 +78,7 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative @Override public void onChange(boolean selfChange, Uri uri) { try { - mRemote.onChange(selfChange, uri); + mRemote.onChange(selfChange, uri, android.os.Process.myUid()); } catch (RemoteException ex) { // Do nothing, the far side is dead } diff --git a/core/java/android/database/IContentObserver.aidl b/core/java/android/database/IContentObserver.aidl index 13aff05..22dc9fe 100644 --- a/core/java/android/database/IContentObserver.aidl +++ b/core/java/android/database/IContentObserver.aidl @@ -2,16 +2,16 @@ ** ** Copyright 2007, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License") +** you may not use this file except in compliance with the License +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -29,5 +29,5 @@ interface IContentObserver * observed. selfUpdate is true if the update was caused by a call to * commit on the cursor that is being observed. */ - oneway void onChange(boolean selfUpdate, in Uri uri); + oneway void onChange(boolean selfUpdate, in Uri uri, int userId); } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 64d3dc5..165148b 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -255,7 +255,7 @@ public final class ContentService extends IContentService.Stub { for (int i=0; i<numCalls; i++) { ObserverCall oc = calls.get(i); try { - oc.mObserver.onChange(oc.mSelfChange, uri); + oc.mObserver.onChange(oc.mSelfChange, uri, userHandle); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri); } diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java index 6a56de0..ce91f3d 100644 --- a/services/print/java/com/android/server/print/PrintManagerService.java +++ b/services/print/java/com/android/server/print/PrintManagerService.java @@ -17,14 +17,14 @@ package com.android.server.print; import android.Manifest; +import android.app.ActivityManager; +import android.app.ActivityManagerNative; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -81,10 +81,13 @@ public final class PrintManagerService extends SystemService { } @Override - public void onBootPhase(int phase) { - if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { - mPrintManagerImpl.systemRunning(); - } + public void onStartUser(int userHandle) { + mPrintManagerImpl.handleUserStarted(userHandle); + } + + @Override + public void onStopUser(int userHandle) { + mPrintManagerImpl.handleUserStopped(userHandle); } class PrintManagerImpl extends IPrintManager.Stub { @@ -101,9 +104,7 @@ public final class PrintManagerService extends SystemService { private final UserManager mUserManager; - private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); - - private int mCurrentUserId = UserHandle.USER_OWNER; + private final SparseArray<UserState> mUserStates = new SparseArray<>(); PrintManagerImpl(Context context) { mContext = context; @@ -112,22 +113,6 @@ public final class PrintManagerService extends SystemService { registerBroadcastReceivers(); } - public void systemRunning() { - BackgroundThread.getHandler().post(new Runnable() { - @Override - public void run() { - final UserState userState; - synchronized (mLock) { - userState = getCurrentUserStateLocked(); - } - // This is the first time we switch to this user after boot, so - // now is the time to remove obsolete print jobs since they - // are from the last boot and no application would query them. - userState.removeObsoletePrintJobs(); - } - }); - } - @Override public Bundle print(String printJobName, IPrintDocumentAdapter adapter, PrintAttributes attributes, String packageName, int appId, int userId) { @@ -137,7 +122,7 @@ public final class PrintManagerService extends SystemService { final String resolvedPackageName; synchronized (mLock) { // Only the current group members can start new print jobs. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return null; } resolvedAppId = resolveCallingAppEnforcingPermissions(appId); @@ -160,7 +145,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can query for state of print jobs. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return null; } resolvedAppId = resolveCallingAppEnforcingPermissions(appId); @@ -181,7 +166,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can query for state of a print job. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return null; } resolvedAppId = resolveCallingAppEnforcingPermissions(appId); @@ -202,7 +187,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can cancel a print job. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } resolvedAppId = resolveCallingAppEnforcingPermissions(appId); @@ -223,7 +208,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can restart a print job. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } resolvedAppId = resolveCallingAppEnforcingPermissions(appId); @@ -243,7 +228,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can get enabled services. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return null; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -262,7 +247,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can get installed services. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return null; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -282,7 +267,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can create a discovery session. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -302,7 +287,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can destroy a discovery session. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -322,7 +307,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can start discovery. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -341,7 +326,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can stop discovery. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -360,7 +345,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can validate printers. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -379,7 +364,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can start printer tracking. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -398,7 +383,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can stop printer tracking. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -419,7 +404,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can add a print job listener. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } resolvedAppId = resolveCallingAppEnforcingPermissions(appId); @@ -440,7 +425,7 @@ public final class PrintManagerService extends SystemService { final UserState userState; synchronized (mLock) { // Only the current group members can remove a print job listener. - if (resolveCallingProfileParentLocked(resolvedUserId) != mCurrentUserId) { + if (resolveCallingProfileParentLocked(resolvedUserId) != getCurrentUserId()) { return; } userState = getOrCreateUserStateLocked(resolvedUserId); @@ -484,11 +469,19 @@ public final class PrintManagerService extends SystemService { Settings.Secure.ENABLED_PRINT_SERVICES); ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) { @Override - public void onChange(boolean selfChange, Uri uri) { + public void onChange(boolean selfChange, Uri uri, int userId) { if (enabledPrintServicesUri.equals(uri)) { synchronized (mLock) { - UserState userState = getCurrentUserStateLocked(); - userState.updateIfNeededLocked(); + if (userId != UserHandle.USER_ALL) { + UserState userState = getOrCreateUserStateLocked(userId); + userState.updateIfNeededLocked(); + } else { + final int userCount = mUserStates.size(); + for (int i = 0; i < userCount; i++) { + UserState userState = mUserStates.valueAt(i); + userState.updateIfNeededLocked(); + } + } } } } @@ -622,27 +615,6 @@ public final class PrintManagerService extends SystemService { // package changes monitor.register(mContext, BackgroundThread.getHandler().getLooper(), UserHandle.ALL, true); - - // user changes - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_USER_SWITCHED); - intentFilter.addAction(Intent.ACTION_USER_REMOVED); - - mContext.registerReceiverAsUser(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (Intent.ACTION_USER_SWITCHED.equals(action)) { - switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); - } else if (Intent.ACTION_USER_REMOVED.equals(action)) { - removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); - } - } - }, UserHandle.ALL, intentFilter, null, BackgroundThread.getHandler()); - } - - private UserState getCurrentUserStateLocked() { - return getOrCreateUserStateLocked(mCurrentUserId); } private UserState getOrCreateUserStateLocked(int userId) { @@ -654,20 +626,11 @@ public final class PrintManagerService extends SystemService { return userState; } - private void switchUser(int newUserId) { + private void handleUserStarted(int userId) { UserState userState; synchronized (mLock) { - if (newUserId == mCurrentUserId) { - return; - } - mCurrentUserId = newUserId; - userState = mUserStates.get(mCurrentUserId); - if (userState == null) { - userState = getCurrentUserStateLocked(); - userState.updateIfNeededLocked(); - } else { - userState.updateIfNeededLocked(); - } + userState = getOrCreateUserStateLocked(userId); + userState.updateIfNeededLocked(); } // This is the first time we switch to this user after boot, so // now is the time to remove obsolete print jobs since they @@ -675,18 +638,18 @@ public final class PrintManagerService extends SystemService { userState.removeObsoletePrintJobs(); } - private void removeUser(int removedUserId) { + private void handleUserStopped(int userId) { synchronized (mLock) { - UserState userState = mUserStates.get(removedUserId); + UserState userState = mUserStates.get(userId); if (userState != null) { userState.destroyLocked(); - mUserStates.remove(removedUserId); + mUserStates.remove(userId); } } } private int resolveCallingProfileParentLocked(int userId) { - if (userId != mCurrentUserId) { + if (userId != getCurrentUserId()) { final long identity = Binder.clearCallingIdentity(); try { UserInfo parent = mUserManager.getProfileParent(userId); @@ -723,28 +686,11 @@ public final class PrintManagerService extends SystemService { } private int resolveCallingUserEnforcingPermissions(int userId) { - final int callingUid = Binder.getCallingUid(); - if (callingUid == 0 || callingUid == Process.SYSTEM_UID - || callingUid == Process.SHELL_UID) { - return userId; - } - final int callingUserId = UserHandle.getUserId(callingUid); - if (callingUserId == userId) { - return userId; - } - if (mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL) - != PackageManager.PERMISSION_GRANTED - && mContext.checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS) - != PackageManager.PERMISSION_GRANTED) { - if (userId == UserHandle.USER_CURRENT_OR_SELF) { - return callingUserId; - } - throw new SecurityException("Call from user " + callingUserId + " as user " - + userId + " without permission INTERACT_ACROSS_USERS or " - + "INTERACT_ACROSS_USERS_FULL not allowed."); - } - if (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF) { - return mCurrentUserId; + try { + return ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(), + Binder.getCallingUid(), userId, true, true, "", null); + } catch (RemoteException re) { + // Shouldn't happen, local. } return userId; } @@ -764,6 +710,15 @@ public final class PrintManagerService extends SystemService { return null; } + private int getCurrentUserId () { + final long identity = Binder.clearCallingIdentity(); + try { + return ActivityManager.getCurrentUser(); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + private void showEnableInstalledPrintServiceNotification(ComponentName component, String label, int userId) { UserHandle userHandle = new UserHandle(userId); |