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

Commit 3f7c9f2d authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Deliver start service args with ParcelledListSlice.

We have seen issues where we fail restarting a process
because there are so many services with so many pending
start arguments that we hit IPC limits.  So instead of
doing an IPC for each service start, collect them together
in a list that is sent once, and send it inside of a
ParcelledListSlice to control how much data is written
inline in the IPC.

Test: boot and ran
Change-Id: Ifed26ccdf535871e577fc02c7ef1d09060ab06ca
parent 265dbc1f
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.res.AssetManager;
@@ -868,17 +869,21 @@ public final class ActivityThread {
            sendMessage(H.UNBIND_SERVICE, s);
        }

        public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
            int flags ,Intent args) {
        public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
            List<ServiceStartArgs> list = args.getList();

            for (int i = 0; i < list.size(); i++) {
                ServiceStartArgs ssa = list.get(i);
                ServiceArgsData s = new ServiceArgsData();
                s.token = token;
            s.taskRemoved = taskRemoved;
            s.startId = startId;
            s.flags = flags;
            s.args = args;
                s.taskRemoved = ssa.taskRemoved;
                s.startId = ssa.startId;
                s.flags = ssa.flags;
                s.args = ssa.args;

                sendMessage(H.SERVICE_ARGS, s);
            }
        }

        public final void scheduleStopService(IBinder token) {
            sendMessage(H.STOP_SERVICE, token);
+2 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.res.CompatibilityInfo;
@@ -86,8 +87,7 @@ oneway interface IApplicationThread {
            in Bundle coreSettings, in String buildSerial);
    void scheduleExit();
    void scheduleConfigurationChanged(in Configuration config);
    void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
            int flags, in Intent args);
    void scheduleServiceArgs(IBinder token, in ParceledListSlice args);
    void updateTimeZone();
    void processInBackground();
    void scheduleBindService(IBinder token,
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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 android.app;

/** @hide */
parcelable ServiceStartArgs;
+82 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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 android.app;

import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * Describes a Service.onStartCommand() request from the system.
 * @hide
 */
public class ServiceStartArgs implements Parcelable {
    final public boolean taskRemoved;
    final public int startId;
    final public int flags;
    final public Intent args;

    public ServiceStartArgs(boolean _taskRemoved, int _startId, int _flags, Intent _args) {
        taskRemoved = _taskRemoved;
        startId = _startId;
        flags = _flags;
        args = _args;
    }

    public String toString() {
        return "ServiceStartArgs{taskRemoved=" + taskRemoved + ", startId=" + startId
                + ", flags=0x" + Integer.toHexString(flags) + ", args=" + args + "}";
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(taskRemoved ? 1 : 0);
        out.writeInt(startId);
        out.writeInt(flags);
        if (args != null) {
            out.writeInt(1);
            args.writeToParcel(out, 0);
        } else {
            out.writeInt(0);
        }
    }

    public static final Parcelable.Creator<ServiceStartArgs> CREATOR
            = new Parcelable.Creator<ServiceStartArgs>() {
        public ServiceStartArgs createFromParcel(Parcel in) {
            return new ServiceStartArgs(in);
        }

        public ServiceStartArgs[] newArray(int size) {
            return new ServiceStartArgs[size];
        }
    };

    public ServiceStartArgs(Parcel in) {
        taskRemoved = in.readInt() != 0;
        startId = in.readInt();
        flags = in.readInt();
        if (in.readInt() != 0) {
            args = Intent.CREATOR.createFromParcel(in);
        } else {
            args = null;
        }
    }
}
+11 −1
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ abstract class BaseParceledListSlice<T> implements Parcelable {

    private final List<T> mList;

    private int mInlineCountLimit = Integer.MAX_VALUE;

    public BaseParceledListSlice(List<T> list) {
        mList = list;
    }
@@ -134,6 +136,14 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
        return mList;
    }

    /**
     * Set a limit on the maximum number of entries in the array that will be included
     * inline in the initial parcelling of this object.
     */
    public void setInlineCountLimit(int maxCount) {
        mInlineCountLimit = maxCount;
    }

    /**
     * Write this to another Parcel. Note that this discards the internal Parcel
     * and should not be used anymore. This is so we can pass this to a Binder
@@ -149,7 +159,7 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
            final Class<?> listElementClass = mList.get(0).getClass();
            writeParcelableCreator(mList.get(0), dest);
            int i = 0;
            while (i < N && dest.dataSize() < MAX_IPC_SIZE) {
            while (i < N && i < mInlineCountLimit && dest.dataSize() < MAX_IPC_SIZE) {
                dest.writeInt(1);

                final T parcelable = mList.get(i);
Loading