Loading services/core/java/android/content/pm/PackageManagerInternal.java +11 −0 Original line number Diff line number Diff line Loading @@ -1139,4 +1139,15 @@ public abstract class PackageManagerInternal { @Checksum.Type int optional, @Checksum.Type int required, @Nullable List trustedInstallers, @NonNull IntentSender statusReceiver, int userId, @NonNull Executor executor, @NonNull Handler handler); /** * Returns true if the given {@code packageName} and {@code userId} is frozen. * * @param packageName a specific package * @param callingUid The uid of the caller * @param userId The user for whom the package is installed * @return {@code true} If the package is current frozen (due to install/update etc.) */ public abstract boolean isPackageFrozen( @NonNull String packageName, int callingUid, int userId); } services/core/java/com/android/server/am/ActiveServices.java +194 −89 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import android.content.Intent; import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; Loading Loading @@ -248,6 +249,11 @@ public final class ActiveServices { */ final ArrayList<ServiceRecord> mPendingFgsNotifications = new ArrayList<>(); /** * Map of services that are asked to be brought up (start/binding) but not ready to. */ private ArrayMap<ServiceRecord, ArrayList<Runnable>> mPendingBringups = new ArrayMap<>(); /** Temporary list for holding the results of calls to {@link #collectPackageServicesLocked} */ private ArrayList<ServiceRecord> mTmpCollectionResults = null; Loading Loading @@ -769,8 +775,13 @@ public final class ActiveServices { fgRequired = false; } NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent( service, callingUid, r.packageName, r.userId); // The package could be frozen (meaning it's doing surgery), defer the actual // start until the package is unfrozen. if (deferServiceBringupIfFrozenLocked(r, service, callingPackage, callingFeatureId, callingUid, callingPid, fgRequired, callerFg, userId, allowBackgroundActivityStarts, backgroundActivityStartsToken, false, null)) { return null; } // If permissions need a review before any of the app components can run, // we do not start the service and launch a review activity if the calling app Loading @@ -779,10 +790,20 @@ public final class ActiveServices { // XXX This is not dealing with fgRequired! if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage, callingFeatureId, callingUid, service, callerFg, userId)) { callingUid, service, callerFg, userId, false, null)) { return null; } return startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg, allowBackgroundActivityStarts, backgroundActivityStartsToken); } private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service, int callingUid, int callingPid, boolean fgRequired, boolean callerFg, boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken) throws TransactionTooLargeException { NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent( service, callingUid, r.packageName, r.userId); if (unscheduleServiceRestartLocked(r, callingUid, false)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r); } Loading Loading @@ -878,30 +899,72 @@ public final class ActiveServices { private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r, String callingPackage, @Nullable String callingFeatureId, int callingUid, Intent service, boolean callerFg, final int userId) { Intent service, boolean callerFg, final int userId, final boolean isBinding, final IServiceConnection connection) { if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( r.packageName, r.userId)) { // Show a permission review UI only for starting from a foreground app // Show a permission review UI only for starting/binding from a foreground app if (!callerFg) { Slog.w(TAG, "u" + r.userId + " Starting a service in package" Slog.w(TAG, "u" + r.userId + (isBinding ? " Binding" : " Starting") + " a service in package" + r.packageName + " requires a permissions review"); return false; } final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, r.packageName); if (isBinding) { RemoteCallback callback = new RemoteCallback( new RemoteCallback.OnResultListener() { @Override public void onResult(Bundle result) { synchronized (mAm) { final long identity = Binder.clearCallingIdentity(); try { if (!mPendingServices.contains(r)) { return; } // If there is still a pending record, then the service // binding request is still valid, so hook them up. We // proceed only if the caller cleared the review requirement // otherwise we unbind because the user didn't approve. if (!mAm.getPackageManagerInternalLocked() .isPermissionsReviewRequired(r.packageName, r.userId)) { try { bringUpServiceLocked(r, service.getFlags(), callerFg, false /* whileRestarting */, false /* permissionsReviewRequired */, false /* packageFrozen */); } catch (RemoteException e) { /* ignore - local call */ } } else { unbindServiceLocked(connection); } } finally { Binder.restoreCallingIdentity(identity); } } } }); intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback); } else { // Starting a service IIntentSender target = mAm.mPendingIntentController.getIntentSender( ActivityManager.INTENT_SENDER_SERVICE, callingPackage, callingFeatureId, callingUid, userId, null, null, 0, new Intent[]{service}, new String[]{service.resolveType(mAm.mContext.getContentResolver())}, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null); final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, r.packageName); intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); } if (DEBUG_PERMISSIONS_REVIEW) { Slog.i(TAG, "u" + r.userId + " Launching permission review for package " Loading @@ -921,6 +984,84 @@ public final class ActiveServices { return true; } /** * Defer the service starting/binding until the package is unfrozen, if it's currently frozen. * * @return {@code true} if the binding is deferred because it's frozen. */ @GuardedBy("mAm") private boolean deferServiceBringupIfFrozenLocked(ServiceRecord s, Intent serviceIntent, String callingPackage, @Nullable String callingFeatureId, int callingUid, int callingPid, boolean fgRequired, boolean callerFg, int userId, boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken, boolean isBinding, IServiceConnection connection) { final PackageManagerInternal pm = mAm.getPackageManagerInternalLocked(); final boolean frozen = pm.isPackageFrozen(s.packageName, callingUid, s.userId); if (!frozen) { // Not frozen, it's okay to go return false; } ArrayList<Runnable> curPendingBringups = mPendingBringups.get(s); if (curPendingBringups == null) { curPendingBringups = new ArrayList<>(); mPendingBringups.put(s, curPendingBringups); } curPendingBringups.add(new Runnable() { @Override public void run() { synchronized (mAm) { if (!mPendingBringups.containsKey(s)) { return; } // binding request is still valid, so hook them up. // Before doing so, check if it requires a permission review. if (!requestStartTargetPermissionsReviewIfNeededLocked(s, callingPackage, callingFeatureId, callingUid, serviceIntent, callerFg, userId, isBinding, connection)) { // Let's wait for the user approval. return; } if (isBinding) { try { bringUpServiceLocked(s, serviceIntent.getFlags(), callerFg, false /* whileRestarting */, false /* permissionsReviewRequired */, false /* packageFrozen */); } catch (TransactionTooLargeException e) { /* ignore - local call */ } } else { // Starting a service try { startServiceInnerLocked(s, serviceIntent, callingUid, callingPid, fgRequired, callerFg, allowBackgroundActivityStarts, backgroundActivityStartsToken); } catch (TransactionTooLargeException e) { /* ignore - local call */ } } } } }); return true; } @GuardedBy("mAm") void schedulePendingServiceStartLocked(String packageName, int userId) { for (int i = mPendingBringups.size() - 1; i >= 0; i--) { final ServiceRecord r = mPendingBringups.keyAt(i); if (r.userId != userId || !TextUtils.equals(r.packageName, packageName)) { continue; } final ArrayList<Runnable> curPendingBringups = mPendingBringups.valueAt(i); if (curPendingBringups != null) { for (int j = curPendingBringups.size() - 1; j >= 0; j--) { curPendingBringups.get(j).run(); } } mPendingBringups.removeAt(i); } } ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ServiceState stracker = r.getTracker(); Loading @@ -932,7 +1073,7 @@ public final class ActiveServices { r.name.getPackageName(), r.name.getClassName(), FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START); mAm.mBatteryStatsService.noteServiceStartRunning(r.stats); String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false, false); if (error != null) { return new ComponentName("!!", error); } Loading Loading @@ -2226,81 +2367,19 @@ public final class ActiveServices { return -1; } ServiceRecord s = res.record; boolean permissionsReviewRequired = false; // The package could be frozen (meaning it's doing surgery), defer the actual // binding until the package is unfrozen. boolean packageFrozen = deferServiceBringupIfFrozenLocked(s, service, callingPackage, null, callingUid, callingPid, false, callerFg, userId, false, null, true, connection); // If permissions need a review before any of the app components can run, // we schedule binding to the service but do not start its process, then // we launch a review activity to which is passed a callback to invoke // when done to start the bound service's process to completing the binding. if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( s.packageName, s.userId)) { permissionsReviewRequired = true; // Show a permission review UI only for binding from a foreground app if (!callerFg) { Slog.w(TAG, "u" + s.userId + " Binding to a service in package" + s.packageName + " requires a permissions review"); return 0; } final ServiceRecord serviceRecord = s; final Intent serviceIntent = service; RemoteCallback callback = new RemoteCallback( new RemoteCallback.OnResultListener() { @Override public void onResult(Bundle result) { synchronized(mAm) { final long identity = Binder.clearCallingIdentity(); try { if (!mPendingServices.contains(serviceRecord)) { return; } // If there is still a pending record, then the service // binding request is still valid, so hook them up. We // proceed only if the caller cleared the review requirement // otherwise we unbind because the user didn't approve. if (!mAm.getPackageManagerInternalLocked() .isPermissionsReviewRequired( serviceRecord.packageName, serviceRecord.userId)) { try { bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), callerFg, false, false); } catch (RemoteException e) { /* ignore - local call */ } } else { unbindServiceLocked(connection); } } finally { Binder.restoreCallingIdentity(identity); } } } }); final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName); intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback); if (DEBUG_PERMISSIONS_REVIEW) { Slog.i(TAG, "u" + s.userId + " Launching permission review for package " + s.packageName); } mAm.mHandler.post(new Runnable() { @Override public void run() { mAm.mContext.startActivityAsUser(intent, new UserHandle(userId)); } }); } boolean permissionsReviewRequired = !packageFrozen && !requestStartTargetPermissionsReviewIfNeededLocked(s, callingPackage, null, callingUid, service, callerFg, userId, true, connection); final long origId = Binder.clearCallingIdentity(); Loading Loading @@ -2374,7 +2453,7 @@ public final class ActiveServices { if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { permissionsReviewRequired, packageFrozen) != null) { return 0; } } Loading Loading @@ -2819,6 +2898,14 @@ public final class ActiveServices { mPendingServices.remove(i); } } for (int i = mPendingBringups.size() - 1; i >= 0; i--) { final ServiceRecord pr = mPendingBringups.keyAt(i); if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid && pr.instanceName.equals(name)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Remove pending bringup: " + pr); mPendingBringups.removeAt(i); } } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Retrieve created new service: " + r); } } catch (RemoteException ex) { Loading Loading @@ -3112,7 +3199,8 @@ public final class ActiveServices { return; } try { bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false, false); } catch (TransactionTooLargeException e) { // Ignore, it's been logged and nothing upstack cares. } Loading Loading @@ -3157,7 +3245,7 @@ public final class ActiveServices { } private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen) throws TransactionTooLargeException { if (r.app != null && r.app.thread != null) { sendServiceArgsLocked(r, execInFg, false); Loading Loading @@ -3251,7 +3339,7 @@ public final class ActiveServices { // Not running -- get it started, and enqueue this service record // to be executed when the app comes up. if (app == null && !permissionsReviewRequired) { if (app == null && !permissionsReviewRequired && !packageFrozen) { // TODO (chriswailes): Change the Zygote policy flags based on if the launch-for-service // was initiated from a notification tap or not. if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, Loading Loading @@ -3653,6 +3741,9 @@ public final class ActiveServices { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r); } } if (mPendingBringups.remove(r) != null) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending bringup: " + r); } cancelForegroundNotificationLocked(r); if (r.isForeground) { Loading Loading @@ -3822,6 +3913,7 @@ public final class ActiveServices { // remove the pending service if (s.getConnections().isEmpty()) { mPendingServices.remove(s); mPendingBringups.remove(s); } if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { Loading Loading @@ -4146,6 +4238,12 @@ public final class ActiveServices { requestUpdateActiveForegroundAppsLocked(smap, 0); } } for (int i = mPendingBringups.size() - 1; i >= 0; i--) { ServiceRecord r = mPendingBringups.keyAt(i); if (TextUtils.equals(r.packageName, packageName) && r.userId == userId) { mPendingBringups.removeAt(i); } } } void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { Loading Loading @@ -4359,6 +4457,13 @@ public final class ActiveServices { mPendingServices.remove(i); } } for (int i = mPendingBringups.size() - 1; i >= 0; i--) { ServiceRecord r = mPendingBringups.keyAt(i); if (r.processName.equals(app.processName) && r.serviceInfo.applicationInfo.uid == app.info.uid) { mPendingBringups.removeAt(i); } } } // Make sure we have no more records on the stopping list. Loading services/core/java/com/android/server/am/ActivityManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -13591,6 +13591,7 @@ public class ActivityManagerService extends IActivityManager.Stub cleanupDisabledPackageComponentsLocked(ssp, userId, intent.getStringArrayExtra( Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST)); mServices.schedulePendingServiceStartLocked(ssp, userId); } } break; Loading
services/core/java/android/content/pm/PackageManagerInternal.java +11 −0 Original line number Diff line number Diff line Loading @@ -1139,4 +1139,15 @@ public abstract class PackageManagerInternal { @Checksum.Type int optional, @Checksum.Type int required, @Nullable List trustedInstallers, @NonNull IntentSender statusReceiver, int userId, @NonNull Executor executor, @NonNull Handler handler); /** * Returns true if the given {@code packageName} and {@code userId} is frozen. * * @param packageName a specific package * @param callingUid The uid of the caller * @param userId The user for whom the package is installed * @return {@code true} If the package is current frozen (due to install/update etc.) */ public abstract boolean isPackageFrozen( @NonNull String packageName, int callingUid, int userId); }
services/core/java/com/android/server/am/ActiveServices.java +194 −89 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import android.content.Intent; import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; Loading Loading @@ -248,6 +249,11 @@ public final class ActiveServices { */ final ArrayList<ServiceRecord> mPendingFgsNotifications = new ArrayList<>(); /** * Map of services that are asked to be brought up (start/binding) but not ready to. */ private ArrayMap<ServiceRecord, ArrayList<Runnable>> mPendingBringups = new ArrayMap<>(); /** Temporary list for holding the results of calls to {@link #collectPackageServicesLocked} */ private ArrayList<ServiceRecord> mTmpCollectionResults = null; Loading Loading @@ -769,8 +775,13 @@ public final class ActiveServices { fgRequired = false; } NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent( service, callingUid, r.packageName, r.userId); // The package could be frozen (meaning it's doing surgery), defer the actual // start until the package is unfrozen. if (deferServiceBringupIfFrozenLocked(r, service, callingPackage, callingFeatureId, callingUid, callingPid, fgRequired, callerFg, userId, allowBackgroundActivityStarts, backgroundActivityStartsToken, false, null)) { return null; } // If permissions need a review before any of the app components can run, // we do not start the service and launch a review activity if the calling app Loading @@ -779,10 +790,20 @@ public final class ActiveServices { // XXX This is not dealing with fgRequired! if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage, callingFeatureId, callingUid, service, callerFg, userId)) { callingUid, service, callerFg, userId, false, null)) { return null; } return startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg, allowBackgroundActivityStarts, backgroundActivityStartsToken); } private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service, int callingUid, int callingPid, boolean fgRequired, boolean callerFg, boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken) throws TransactionTooLargeException { NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent( service, callingUid, r.packageName, r.userId); if (unscheduleServiceRestartLocked(r, callingUid, false)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r); } Loading Loading @@ -878,30 +899,72 @@ public final class ActiveServices { private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r, String callingPackage, @Nullable String callingFeatureId, int callingUid, Intent service, boolean callerFg, final int userId) { Intent service, boolean callerFg, final int userId, final boolean isBinding, final IServiceConnection connection) { if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( r.packageName, r.userId)) { // Show a permission review UI only for starting from a foreground app // Show a permission review UI only for starting/binding from a foreground app if (!callerFg) { Slog.w(TAG, "u" + r.userId + " Starting a service in package" Slog.w(TAG, "u" + r.userId + (isBinding ? " Binding" : " Starting") + " a service in package" + r.packageName + " requires a permissions review"); return false; } final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, r.packageName); if (isBinding) { RemoteCallback callback = new RemoteCallback( new RemoteCallback.OnResultListener() { @Override public void onResult(Bundle result) { synchronized (mAm) { final long identity = Binder.clearCallingIdentity(); try { if (!mPendingServices.contains(r)) { return; } // If there is still a pending record, then the service // binding request is still valid, so hook them up. We // proceed only if the caller cleared the review requirement // otherwise we unbind because the user didn't approve. if (!mAm.getPackageManagerInternalLocked() .isPermissionsReviewRequired(r.packageName, r.userId)) { try { bringUpServiceLocked(r, service.getFlags(), callerFg, false /* whileRestarting */, false /* permissionsReviewRequired */, false /* packageFrozen */); } catch (RemoteException e) { /* ignore - local call */ } } else { unbindServiceLocked(connection); } } finally { Binder.restoreCallingIdentity(identity); } } } }); intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback); } else { // Starting a service IIntentSender target = mAm.mPendingIntentController.getIntentSender( ActivityManager.INTENT_SENDER_SERVICE, callingPackage, callingFeatureId, callingUid, userId, null, null, 0, new Intent[]{service}, new String[]{service.resolveType(mAm.mContext.getContentResolver())}, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE, null); final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, r.packageName); intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); } if (DEBUG_PERMISSIONS_REVIEW) { Slog.i(TAG, "u" + r.userId + " Launching permission review for package " Loading @@ -921,6 +984,84 @@ public final class ActiveServices { return true; } /** * Defer the service starting/binding until the package is unfrozen, if it's currently frozen. * * @return {@code true} if the binding is deferred because it's frozen. */ @GuardedBy("mAm") private boolean deferServiceBringupIfFrozenLocked(ServiceRecord s, Intent serviceIntent, String callingPackage, @Nullable String callingFeatureId, int callingUid, int callingPid, boolean fgRequired, boolean callerFg, int userId, boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken, boolean isBinding, IServiceConnection connection) { final PackageManagerInternal pm = mAm.getPackageManagerInternalLocked(); final boolean frozen = pm.isPackageFrozen(s.packageName, callingUid, s.userId); if (!frozen) { // Not frozen, it's okay to go return false; } ArrayList<Runnable> curPendingBringups = mPendingBringups.get(s); if (curPendingBringups == null) { curPendingBringups = new ArrayList<>(); mPendingBringups.put(s, curPendingBringups); } curPendingBringups.add(new Runnable() { @Override public void run() { synchronized (mAm) { if (!mPendingBringups.containsKey(s)) { return; } // binding request is still valid, so hook them up. // Before doing so, check if it requires a permission review. if (!requestStartTargetPermissionsReviewIfNeededLocked(s, callingPackage, callingFeatureId, callingUid, serviceIntent, callerFg, userId, isBinding, connection)) { // Let's wait for the user approval. return; } if (isBinding) { try { bringUpServiceLocked(s, serviceIntent.getFlags(), callerFg, false /* whileRestarting */, false /* permissionsReviewRequired */, false /* packageFrozen */); } catch (TransactionTooLargeException e) { /* ignore - local call */ } } else { // Starting a service try { startServiceInnerLocked(s, serviceIntent, callingUid, callingPid, fgRequired, callerFg, allowBackgroundActivityStarts, backgroundActivityStartsToken); } catch (TransactionTooLargeException e) { /* ignore - local call */ } } } } }); return true; } @GuardedBy("mAm") void schedulePendingServiceStartLocked(String packageName, int userId) { for (int i = mPendingBringups.size() - 1; i >= 0; i--) { final ServiceRecord r = mPendingBringups.keyAt(i); if (r.userId != userId || !TextUtils.equals(r.packageName, packageName)) { continue; } final ArrayList<Runnable> curPendingBringups = mPendingBringups.valueAt(i); if (curPendingBringups != null) { for (int j = curPendingBringups.size() - 1; j >= 0; j--) { curPendingBringups.get(j).run(); } } mPendingBringups.removeAt(i); } } ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ServiceState stracker = r.getTracker(); Loading @@ -932,7 +1073,7 @@ public final class ActiveServices { r.name.getPackageName(), r.name.getClassName(), FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START); mAm.mBatteryStatsService.noteServiceStartRunning(r.stats); String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false, false); if (error != null) { return new ComponentName("!!", error); } Loading Loading @@ -2226,81 +2367,19 @@ public final class ActiveServices { return -1; } ServiceRecord s = res.record; boolean permissionsReviewRequired = false; // The package could be frozen (meaning it's doing surgery), defer the actual // binding until the package is unfrozen. boolean packageFrozen = deferServiceBringupIfFrozenLocked(s, service, callingPackage, null, callingUid, callingPid, false, callerFg, userId, false, null, true, connection); // If permissions need a review before any of the app components can run, // we schedule binding to the service but do not start its process, then // we launch a review activity to which is passed a callback to invoke // when done to start the bound service's process to completing the binding. if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( s.packageName, s.userId)) { permissionsReviewRequired = true; // Show a permission review UI only for binding from a foreground app if (!callerFg) { Slog.w(TAG, "u" + s.userId + " Binding to a service in package" + s.packageName + " requires a permissions review"); return 0; } final ServiceRecord serviceRecord = s; final Intent serviceIntent = service; RemoteCallback callback = new RemoteCallback( new RemoteCallback.OnResultListener() { @Override public void onResult(Bundle result) { synchronized(mAm) { final long identity = Binder.clearCallingIdentity(); try { if (!mPendingServices.contains(serviceRecord)) { return; } // If there is still a pending record, then the service // binding request is still valid, so hook them up. We // proceed only if the caller cleared the review requirement // otherwise we unbind because the user didn't approve. if (!mAm.getPackageManagerInternalLocked() .isPermissionsReviewRequired( serviceRecord.packageName, serviceRecord.userId)) { try { bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), callerFg, false, false); } catch (RemoteException e) { /* ignore - local call */ } } else { unbindServiceLocked(connection); } } finally { Binder.restoreCallingIdentity(identity); } } } }); final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName); intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback); if (DEBUG_PERMISSIONS_REVIEW) { Slog.i(TAG, "u" + s.userId + " Launching permission review for package " + s.packageName); } mAm.mHandler.post(new Runnable() { @Override public void run() { mAm.mContext.startActivityAsUser(intent, new UserHandle(userId)); } }); } boolean permissionsReviewRequired = !packageFrozen && !requestStartTargetPermissionsReviewIfNeededLocked(s, callingPackage, null, callingUid, service, callerFg, userId, true, connection); final long origId = Binder.clearCallingIdentity(); Loading Loading @@ -2374,7 +2453,7 @@ public final class ActiveServices { if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { permissionsReviewRequired, packageFrozen) != null) { return 0; } } Loading Loading @@ -2819,6 +2898,14 @@ public final class ActiveServices { mPendingServices.remove(i); } } for (int i = mPendingBringups.size() - 1; i >= 0; i--) { final ServiceRecord pr = mPendingBringups.keyAt(i); if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid && pr.instanceName.equals(name)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Remove pending bringup: " + pr); mPendingBringups.removeAt(i); } } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Retrieve created new service: " + r); } } catch (RemoteException ex) { Loading Loading @@ -3112,7 +3199,8 @@ public final class ActiveServices { return; } try { bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false, false); } catch (TransactionTooLargeException e) { // Ignore, it's been logged and nothing upstack cares. } Loading Loading @@ -3157,7 +3245,7 @@ public final class ActiveServices { } private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen) throws TransactionTooLargeException { if (r.app != null && r.app.thread != null) { sendServiceArgsLocked(r, execInFg, false); Loading Loading @@ -3251,7 +3339,7 @@ public final class ActiveServices { // Not running -- get it started, and enqueue this service record // to be executed when the app comes up. if (app == null && !permissionsReviewRequired) { if (app == null && !permissionsReviewRequired && !packageFrozen) { // TODO (chriswailes): Change the Zygote policy flags based on if the launch-for-service // was initiated from a notification tap or not. if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, Loading Loading @@ -3653,6 +3741,9 @@ public final class ActiveServices { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r); } } if (mPendingBringups.remove(r) != null) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending bringup: " + r); } cancelForegroundNotificationLocked(r); if (r.isForeground) { Loading Loading @@ -3822,6 +3913,7 @@ public final class ActiveServices { // remove the pending service if (s.getConnections().isEmpty()) { mPendingServices.remove(s); mPendingBringups.remove(s); } if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { Loading Loading @@ -4146,6 +4238,12 @@ public final class ActiveServices { requestUpdateActiveForegroundAppsLocked(smap, 0); } } for (int i = mPendingBringups.size() - 1; i >= 0; i--) { ServiceRecord r = mPendingBringups.keyAt(i); if (TextUtils.equals(r.packageName, packageName) && r.userId == userId) { mPendingBringups.removeAt(i); } } } void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { Loading Loading @@ -4359,6 +4457,13 @@ public final class ActiveServices { mPendingServices.remove(i); } } for (int i = mPendingBringups.size() - 1; i >= 0; i--) { ServiceRecord r = mPendingBringups.keyAt(i); if (r.processName.equals(app.processName) && r.serviceInfo.applicationInfo.uid == app.info.uid) { mPendingBringups.removeAt(i); } } } // Make sure we have no more records on the stopping list. Loading
services/core/java/com/android/server/am/ActivityManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -13591,6 +13591,7 @@ public class ActivityManagerService extends IActivityManager.Stub cleanupDisabledPackageComponentsLocked(ssp, userId, intent.getStringArrayExtra( Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST)); mServices.schedulePendingServiceStartLocked(ssp, userId); } } break;