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

Commit 427b75f8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Introduced ActivityServiceConnectionsHolder (18/n)"

parents 495de00e c4e63a46
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
}
+6 −11
Original line number Diff line number Diff line
@@ -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;
@@ -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();
@@ -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;
@@ -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);
+20 −6
Original line number Diff line number Diff line
@@ -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;
@@ -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) {
@@ -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));
            }
        }
    }
    /**
+3 −3
Original line number Diff line number Diff line
@@ -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
@@ -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));
+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