Loading core/java/android/app/ActivityManagerInternal.java +2 −0 Original line number Diff line number Diff line Loading @@ -245,4 +245,6 @@ public abstract class ActivityManagerInternal { public abstract ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, boolean fgRequired, String callingPackage, int userId) throws TransactionTooLargeException; public abstract void disconnectActivityFromServices(Object connectionHolder); } services/core/java/com/android/server/am/ActiveServices.java +6 −11 Original line number Diff line number Diff line Loading @@ -1466,9 +1466,9 @@ public final class ActiveServices { + ") when binding service " + service); } ActivityRecord activity = null; ActivityServiceConnectionsHolder<ConnectionRecord> activity = null; if (token != null) { activity = ActivityRecord.isInStackLocked(token); activity = mAm.mAtmInternal.getServiceConnectionsHolder(token); if (activity == null) { Slog.w(TAG, "Binding with unknown activity: " + token); return 0; Loading Loading @@ -1644,10 +1644,7 @@ public final class ActiveServices { clist.add(c); b.connections.add(c); if (activity != null) { if (activity.connections == null) { activity.connections = new HashSet<ConnectionRecord>(); } activity.connections.add(c); activity.addConnection(c); } b.client.connections.add(c); c.startAssociationIfNeeded(); Loading Loading @@ -2861,8 +2858,8 @@ public final class ActiveServices { smap.ensureNotStartingBackgroundLocked(r); } void removeConnectionLocked( ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) { void removeConnectionLocked(ConnectionRecord c, ProcessRecord skipApp, ActivityServiceConnectionsHolder skipAct) { IBinder binder = c.conn.asBinder(); AppBindRecord b = c.binding; ServiceRecord s = b.service; Loading @@ -2876,9 +2873,7 @@ public final class ActiveServices { b.connections.remove(c); c.stopAssociation(); if (c.activity != null && c.activity != skipAct) { if (c.activity.connections != null) { c.activity.connections.remove(c); } c.activity.removeConnection(c); } if (b.client != skipApp) { b.client.connections.remove(c); Loading services/core/java/com/android/server/am/ActivityManagerService.java +20 −6 Original line number Diff line number Diff line Loading @@ -10606,9 +10606,13 @@ public class ActivityManagerService extends IActivityManager.Stub currApp.importanceReasonImportance = ActivityManager.RunningAppProcessInfo.procStateToImportance( app.adjSourceProcState); } else if (app.adjSource instanceof ActivityRecord) { ActivityRecord r = (ActivityRecord)app.adjSource; if (r.app != null) currApp.importanceReasonPid = r.app.getPid(); } else if (app.adjSource instanceof ActivityServiceConnectionsHolder) { ActivityServiceConnectionsHolder r = (ActivityServiceConnectionsHolder) app.adjSource; final int pid = r.getActivityPid(); if (pid != -1) { currApp.importanceReasonPid = pid; } } if (app.adjTarget instanceof ComponentName) { currApp.importanceReasonComponent = (ComponentName)app.adjTarget; Loading Loading @@ -17783,10 +17787,10 @@ public class ActivityManagerService extends IActivityManager.Stub if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { app.treatLikeActivity = true; } final ActivityRecord a = cr.activity; final ActivityServiceConnectionsHolder a = cr.activity; if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) { if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && (a.visible || a.isState(ActivityState.RESUMED, ActivityState.PAUSING))) { if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && a.isActivityVisible()) { adj = ProcessList.FOREGROUND_APP_ADJ; if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { if ((cr.flags&Context.BIND_IMPORTANT) != 0) { Loading Loading @@ -20901,6 +20905,16 @@ public class ActivityManagerService extends IActivityManager.Stub return res; } } @Override public void disconnectActivityFromServices(Object connectionHolder) { synchronized(ActivityManagerService.this) { final ActivityServiceConnectionsHolder c = (ActivityServiceConnectionsHolder) connectionHolder; c.forEachConnection(cr -> mServices.removeConnectionLocked( (ConnectionRecord) cr, null, c)); } } } /** services/core/java/com/android/server/am/ActivityRecord.java +3 −3 Original line number Diff line number Diff line Loading @@ -283,7 +283,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo ActivityOptions pendingOptions; // most recently given options ActivityOptions returningOptions; // options that are coming back via convertToTranslucent AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections. UriPermissionOwner uriPermissions; // current special URI access perms. WindowProcessController app; // if non-null, hosting application private ActivityState mState; // current state we are in Loading Loading @@ -549,8 +549,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo pw.print(" configChangeFlags="); pw.println(Integer.toHexString(configChangeFlags)); } if (connections != null) { pw.print(prefix); pw.print("connections="); pw.println(connections); if (mServiceConnectionsHolder != null) { pw.print(prefix); pw.print("connections="); pw.println(mServiceConnectionsHolder); } if (info != null) { pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode)); Loading services/core/java/com/android/server/am/ActivityServiceConnectionsHolder.java 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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 * * 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 * limitations under the License */ package com.android.server.am; import static com.android.server.am.ActivityStack.ActivityState.PAUSING; import static com.android.server.am.ActivityStack.ActivityState.RESUMED; import java.io.PrintWriter; import java.util.HashSet; import java.util.Iterator; import java.util.function.Consumer; /** * Class for tracking the connections to services on the AM side that activities on the * WM side (in the future) bind with for things like oom score adjustment. Would normally be one * instance of this per activity for tracking all services connected to that activity. AM will * sometimes query this to bump the OOM score for the processes with services connected to visible * activities. */ public class ActivityServiceConnectionsHolder<T> { private final ActivityTaskManagerService mService; /** The activity the owns this service connection object. */ private final ActivityRecord mActivity; /** * The service connection object bounded with the owning activity. They represent * ConnectionRecord on the AM side, however we don't need to know their object representation * on the WM side since we don't perform operations on the object. Mainly here for communication * and booking with the AM side. */ private HashSet<T> mConnections; ActivityServiceConnectionsHolder(ActivityTaskManagerService service, ActivityRecord activity) { mService = service; mActivity = activity; } /** Adds a connection record that the activity has bound to a specific service. */ public void addConnection(T c) { synchronized (mService.mGlobalLock) { if (mConnections == null) { mConnections = new HashSet<>(); } mConnections.add(c); } } /** Removed a connection record between the activity and a specific service. */ public void removeConnection(T c) { synchronized (mService.mGlobalLock) { if (mConnections == null) { return; } mConnections.remove(c); } } public boolean isActivityVisible() { synchronized (mService.mGlobalLock) { return mActivity.visible || mActivity.isState(RESUMED, PAUSING); } } public int getActivityPid() { synchronized (mService.mGlobalLock) { return mActivity.hasProcess() ? mActivity.app.getPid() : -1; } } public void forEachConnection(Consumer<T> consumer) { synchronized (mService.mGlobalLock) { if (mConnections == null || mConnections.isEmpty()) { return; } final Iterator<T> it = mConnections.iterator(); while (it.hasNext()) { T c = it.next(); consumer.accept(c); } } } /** Removes the connection between the activity and all services that were connected to it. */ void disconnectActivityFromServices() { if (mConnections == null || mConnections.isEmpty()) { return; } mService.mH.post(() -> mService.mAmInternal.disconnectActivityFromServices(this)); } public void dump(PrintWriter pw, String prefix) { synchronized (mService.mGlobalLock) { pw.println(prefix + "activity=" + mActivity); } } } Loading
core/java/android/app/ActivityManagerInternal.java +2 −0 Original line number Diff line number Diff line Loading @@ -245,4 +245,6 @@ public abstract class ActivityManagerInternal { public abstract ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, boolean fgRequired, String callingPackage, int userId) throws TransactionTooLargeException; public abstract void disconnectActivityFromServices(Object connectionHolder); }
services/core/java/com/android/server/am/ActiveServices.java +6 −11 Original line number Diff line number Diff line Loading @@ -1466,9 +1466,9 @@ public final class ActiveServices { + ") when binding service " + service); } ActivityRecord activity = null; ActivityServiceConnectionsHolder<ConnectionRecord> activity = null; if (token != null) { activity = ActivityRecord.isInStackLocked(token); activity = mAm.mAtmInternal.getServiceConnectionsHolder(token); if (activity == null) { Slog.w(TAG, "Binding with unknown activity: " + token); return 0; Loading Loading @@ -1644,10 +1644,7 @@ public final class ActiveServices { clist.add(c); b.connections.add(c); if (activity != null) { if (activity.connections == null) { activity.connections = new HashSet<ConnectionRecord>(); } activity.connections.add(c); activity.addConnection(c); } b.client.connections.add(c); c.startAssociationIfNeeded(); Loading Loading @@ -2861,8 +2858,8 @@ public final class ActiveServices { smap.ensureNotStartingBackgroundLocked(r); } void removeConnectionLocked( ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) { void removeConnectionLocked(ConnectionRecord c, ProcessRecord skipApp, ActivityServiceConnectionsHolder skipAct) { IBinder binder = c.conn.asBinder(); AppBindRecord b = c.binding; ServiceRecord s = b.service; Loading @@ -2876,9 +2873,7 @@ public final class ActiveServices { b.connections.remove(c); c.stopAssociation(); if (c.activity != null && c.activity != skipAct) { if (c.activity.connections != null) { c.activity.connections.remove(c); } c.activity.removeConnection(c); } if (b.client != skipApp) { b.client.connections.remove(c); Loading
services/core/java/com/android/server/am/ActivityManagerService.java +20 −6 Original line number Diff line number Diff line Loading @@ -10606,9 +10606,13 @@ public class ActivityManagerService extends IActivityManager.Stub currApp.importanceReasonImportance = ActivityManager.RunningAppProcessInfo.procStateToImportance( app.adjSourceProcState); } else if (app.adjSource instanceof ActivityRecord) { ActivityRecord r = (ActivityRecord)app.adjSource; if (r.app != null) currApp.importanceReasonPid = r.app.getPid(); } else if (app.adjSource instanceof ActivityServiceConnectionsHolder) { ActivityServiceConnectionsHolder r = (ActivityServiceConnectionsHolder) app.adjSource; final int pid = r.getActivityPid(); if (pid != -1) { currApp.importanceReasonPid = pid; } } if (app.adjTarget instanceof ComponentName) { currApp.importanceReasonComponent = (ComponentName)app.adjTarget; Loading Loading @@ -17783,10 +17787,10 @@ public class ActivityManagerService extends IActivityManager.Stub if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { app.treatLikeActivity = true; } final ActivityRecord a = cr.activity; final ActivityServiceConnectionsHolder a = cr.activity; if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) { if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && (a.visible || a.isState(ActivityState.RESUMED, ActivityState.PAUSING))) { if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && a.isActivityVisible()) { adj = ProcessList.FOREGROUND_APP_ADJ; if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { if ((cr.flags&Context.BIND_IMPORTANT) != 0) { Loading Loading @@ -20901,6 +20905,16 @@ public class ActivityManagerService extends IActivityManager.Stub return res; } } @Override public void disconnectActivityFromServices(Object connectionHolder) { synchronized(ActivityManagerService.this) { final ActivityServiceConnectionsHolder c = (ActivityServiceConnectionsHolder) connectionHolder; c.forEachConnection(cr -> mServices.removeConnectionLocked( (ConnectionRecord) cr, null, c)); } } } /**
services/core/java/com/android/server/am/ActivityRecord.java +3 −3 Original line number Diff line number Diff line Loading @@ -283,7 +283,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo ActivityOptions pendingOptions; // most recently given options ActivityOptions returningOptions; // options that are coming back via convertToTranslucent AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections. UriPermissionOwner uriPermissions; // current special URI access perms. WindowProcessController app; // if non-null, hosting application private ActivityState mState; // current state we are in Loading Loading @@ -549,8 +549,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo pw.print(" configChangeFlags="); pw.println(Integer.toHexString(configChangeFlags)); } if (connections != null) { pw.print(prefix); pw.print("connections="); pw.println(connections); if (mServiceConnectionsHolder != null) { pw.print(prefix); pw.print("connections="); pw.println(mServiceConnectionsHolder); } if (info != null) { pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode)); Loading
services/core/java/com/android/server/am/ActivityServiceConnectionsHolder.java 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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 * * 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 * limitations under the License */ package com.android.server.am; import static com.android.server.am.ActivityStack.ActivityState.PAUSING; import static com.android.server.am.ActivityStack.ActivityState.RESUMED; import java.io.PrintWriter; import java.util.HashSet; import java.util.Iterator; import java.util.function.Consumer; /** * Class for tracking the connections to services on the AM side that activities on the * WM side (in the future) bind with for things like oom score adjustment. Would normally be one * instance of this per activity for tracking all services connected to that activity. AM will * sometimes query this to bump the OOM score for the processes with services connected to visible * activities. */ public class ActivityServiceConnectionsHolder<T> { private final ActivityTaskManagerService mService; /** The activity the owns this service connection object. */ private final ActivityRecord mActivity; /** * The service connection object bounded with the owning activity. They represent * ConnectionRecord on the AM side, however we don't need to know their object representation * on the WM side since we don't perform operations on the object. Mainly here for communication * and booking with the AM side. */ private HashSet<T> mConnections; ActivityServiceConnectionsHolder(ActivityTaskManagerService service, ActivityRecord activity) { mService = service; mActivity = activity; } /** Adds a connection record that the activity has bound to a specific service. */ public void addConnection(T c) { synchronized (mService.mGlobalLock) { if (mConnections == null) { mConnections = new HashSet<>(); } mConnections.add(c); } } /** Removed a connection record between the activity and a specific service. */ public void removeConnection(T c) { synchronized (mService.mGlobalLock) { if (mConnections == null) { return; } mConnections.remove(c); } } public boolean isActivityVisible() { synchronized (mService.mGlobalLock) { return mActivity.visible || mActivity.isState(RESUMED, PAUSING); } } public int getActivityPid() { synchronized (mService.mGlobalLock) { return mActivity.hasProcess() ? mActivity.app.getPid() : -1; } } public void forEachConnection(Consumer<T> consumer) { synchronized (mService.mGlobalLock) { if (mConnections == null || mConnections.isEmpty()) { return; } final Iterator<T> it = mConnections.iterator(); while (it.hasNext()) { T c = it.next(); consumer.accept(c); } } } /** Removes the connection between the activity and all services that were connected to it. */ void disconnectActivityFromServices() { if (mConnections == null || mConnections.isEmpty()) { return; } mService.mH.post(() -> mService.mAmInternal.disconnectActivityFromServices(this)); } public void dump(PrintWriter pw, String prefix) { synchronized (mService.mGlobalLock) { pw.println(prefix + "activity=" + mActivity); } } }