Loading services/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ java_library { "services.net", "services.print", "services.restrictions", "services.startop", "services.usage", "services.usb", "services.voiceinteraction", Loading services/java/com/android/server/SystemServer.java +5 −1 Original line number Diff line number Diff line Loading @@ -145,6 +145,7 @@ import com.android.server.webkit.WebViewUpdateService; import com.android.server.wm.ActivityTaskManagerService; import com.android.server.wm.WindowManagerGlobalLock; import com.android.server.wm.WindowManagerService; import com.google.android.startop.iorap.IorapForwardingService; import dalvik.system.VMRuntime; Loading Loading @@ -1007,10 +1008,13 @@ public final class SystemServer { mSystemServiceManager.startService(PinnerService.class); traceEnd(); traceBeginAndSlog("IorapForwardingService"); mSystemServiceManager.startService(IorapForwardingService.class); traceEnd(); traceBeginAndSlog("SignedConfigService"); SignedConfigService.registerUpdateReceiver(mSystemContext); traceEnd(); } catch (RuntimeException e) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting core service", e); Loading services/startop/Android.bp 0 → 100644 +24 −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. */ java_library_static { name: "services.startop", static_libs: [ // frameworks/base/startop/iorap "services.startop.iorap", ], } startop/iorap/Android.bp +3 −1 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ // limitations under the License. java_library_static { name: "libiorap-java", name: "services.startop.iorap", aidl: { include_dirs: [ Loading @@ -21,6 +21,8 @@ java_library_static { ], }, libs: ["services.core"], srcs: [ ":iorap-aidl", "**/*.java", Loading startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java 0 → 100644 +368 −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.google.android.startop.iorap; import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Parcel; import android.os.Parcelable; // TODO: fix this. either move this class into system server or add a dependency on // these wm classes to libiorap-java and libiorap-java-tests (somehow). import com.android.server.wm.ActivityMetricsLaunchObserver; import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto; import com.android.server.wm.ActivityMetricsLaunchObserver.Temperature; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.InvocationTargetException; import java.util.Objects; /** * Provide a hint to iorapd that an app launch sequence has transitioned state.<br /><br /> * * Knowledge of when an activity starts/stops can be used by iorapd to increase system * performance (e.g. by launching perfetto tracing to record an io profile, or by * playing back an ioprofile via readahead) over the long run.<br /><br /> * * /@see com.google.android.startop.iorap.IIorap#onAppLaunchEvent <br /><br /> * @see com.android.server.wm.ActivityMetricsLaunchObserver * ActivityMetricsLaunchObserver for the possible event states. * @hide */ public abstract class AppLaunchEvent implements Parcelable { @LongDef @Retention(RetentionPolicy.SOURCE) public @interface SequenceId {} public final @SequenceId long sequenceId; protected AppLaunchEvent(@SequenceId long sequenceId) { this.sequenceId = sequenceId; } @Override public boolean equals(Object other) { if (other instanceof AppLaunchEvent) { return equals((AppLaunchEvent) other); } return false; } protected boolean equals(AppLaunchEvent other) { return sequenceId == other.sequenceId; } @Override public String toString() { return getClass().getSimpleName() + "{" + "sequenceId=" + Long.toString(sequenceId) + toStringBody() + "}"; } protected String toStringBody() { return ""; }; // List of possible variants: public static final class IntentStarted extends AppLaunchEvent { @NonNull public final Intent intent; public IntentStarted(@SequenceId long sequenceId, Intent intent) { super(sequenceId); this.intent = intent; Objects.requireNonNull(intent, "intent"); } @Override public boolean equals(Object other) { if (other instanceof IntentStarted) { return intent.equals(((IntentStarted)other).intent) && super.equals(other); } return false; } @Override protected String toStringBody() { return ", intent=" + intent.toString(); } @Override protected void writeToParcelImpl(Parcel p, int flags) { super.writeToParcelImpl(p, flags); intent.writeToParcel(p, flags); } IntentStarted(Parcel p) { super(p); intent = Intent.CREATOR.createFromParcel(p); } } public static final class IntentFailed extends AppLaunchEvent { public IntentFailed(@SequenceId long sequenceId) { super(sequenceId); } @Override public boolean equals(Object other) { if (other instanceof IntentFailed) { return super.equals(other); } return false; } IntentFailed(Parcel p) { super(p); } } public static abstract class BaseWithActivityRecordData extends AppLaunchEvent { public final @NonNull @ActivityRecordProto byte[] activityRecordSnapshot; protected BaseWithActivityRecordData(@SequenceId long sequenceId, @NonNull @ActivityRecordProto byte[] snapshot) { super(sequenceId); activityRecordSnapshot = snapshot; Objects.requireNonNull(snapshot, "snapshot"); } @Override public boolean equals(Object other) { if (other instanceof BaseWithActivityRecordData) { return activityRecordSnapshot.equals( ((BaseWithActivityRecordData)other).activityRecordSnapshot) && super.equals(other); } return false; } @Override protected String toStringBody() { return ", " + activityRecordSnapshot.toString(); } @Override protected void writeToParcelImpl(Parcel p, int flags) { super.writeToParcelImpl(p, flags); ActivityRecordProtoParcelable.write(p, activityRecordSnapshot, flags); } BaseWithActivityRecordData(Parcel p) { super(p); activityRecordSnapshot = ActivityRecordProtoParcelable.create(p); } } public static final class ActivityLaunched extends BaseWithActivityRecordData { public final @ActivityMetricsLaunchObserver.Temperature int temperature; public ActivityLaunched(@SequenceId long sequenceId, @NonNull @ActivityRecordProto byte[] snapshot, @ActivityMetricsLaunchObserver.Temperature int temperature) { super(sequenceId, snapshot); this.temperature = temperature; } @Override public boolean equals(Object other) { if (other instanceof ActivityLaunched) { return temperature == ((ActivityLaunched)other).temperature && super.equals(other); } return false; } @Override protected String toStringBody() { return ", temperature=" + Integer.toString(temperature); } @Override protected void writeToParcelImpl(Parcel p, int flags) { super.writeToParcelImpl(p, flags); p.writeInt(temperature); } ActivityLaunched(Parcel p) { super(p); temperature = p.readInt(); } } public static final class ActivityLaunchFinished extends BaseWithActivityRecordData { public ActivityLaunchFinished(@SequenceId long sequenceId, @NonNull @ActivityRecordProto byte[] snapshot) { super(sequenceId, snapshot); } @Override public boolean equals(Object other) { if (other instanceof ActivityLaunched) { return super.equals(other); } return false; } } public static class ActivityLaunchCancelled extends AppLaunchEvent { public final @Nullable @ActivityRecordProto byte[] activityRecordSnapshot; public ActivityLaunchCancelled(@SequenceId long sequenceId, @Nullable @ActivityRecordProto byte[] snapshot) { super(sequenceId); activityRecordSnapshot = snapshot; } @Override public boolean equals(Object other) { if (other instanceof ActivityLaunchCancelled) { return Objects.equals(activityRecordSnapshot, ((ActivityLaunchCancelled)other).activityRecordSnapshot) && super.equals(other); } return false; } @Override protected String toStringBody() { return ", " + activityRecordSnapshot.toString(); } @Override protected void writeToParcelImpl(Parcel p, int flags) { super.writeToParcelImpl(p, flags); if (activityRecordSnapshot != null) { p.writeBoolean(true); ActivityRecordProtoParcelable.write(p, activityRecordSnapshot, flags); } else { p.writeBoolean(false); } } ActivityLaunchCancelled(Parcel p) { super(p); if (p.readBoolean()) { activityRecordSnapshot = ActivityRecordProtoParcelable.create(p); } else { activityRecordSnapshot = null; } } } @Override public @ContentsFlags int describeContents() { return 0; } @Override public void writeToParcel(Parcel p, @WriteFlags int flags) { p.writeInt(getTypeIndex()); writeToParcelImpl(p, flags); } public static Creator<AppLaunchEvent> CREATOR = new Creator<AppLaunchEvent>() { @Override public AppLaunchEvent createFromParcel(Parcel source) { int typeIndex = source.readInt(); Class<?> kls = getClassFromTypeIndex(typeIndex); if (kls == null) { throw new IllegalArgumentException("Invalid type index: " + typeIndex); } try { return (AppLaunchEvent) kls.getConstructor(Parcel.class).newInstance(source); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } @Override public AppLaunchEvent[] newArray(int size) { return new AppLaunchEvent[0]; } }; protected void writeToParcelImpl(Parcel p, int flags) { p.writeLong(sequenceId); } protected AppLaunchEvent(Parcel p) { sequenceId = p.readLong(); } private int getTypeIndex() { for (int i = 0; i < sTypes.length; ++i) { if (sTypes[i].equals(this.getClass())) { return i; } } throw new AssertionError("sTypes did not include this type: " + this.getClass()); } private static @Nullable Class<?> getClassFromTypeIndex(int typeIndex) { if (typeIndex >= 0 && typeIndex < sTypes.length) { return sTypes[typeIndex]; } return null; } // Index position matters: It is used to encode the specific type in parceling. // Keep up-to-date with C++ side. private static Class<?>[] sTypes = new Class[] { IntentStarted.class, IntentFailed.class, ActivityLaunched.class, ActivityLaunchFinished.class, ActivityLaunchCancelled.class, }; // TODO: move to @ActivityRecordProto byte[] once we have unit tests. public static class ActivityRecordProtoParcelable { public static void write(Parcel p, @ActivityRecordProto byte[] activityRecordSnapshot, int flags) { p.writeByteArray(activityRecordSnapshot); } public static @ActivityRecordProto byte[] create(Parcel p) { byte[] data = p.createByteArray(); return data; } } } Loading
services/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ java_library { "services.net", "services.print", "services.restrictions", "services.startop", "services.usage", "services.usb", "services.voiceinteraction", Loading
services/java/com/android/server/SystemServer.java +5 −1 Original line number Diff line number Diff line Loading @@ -145,6 +145,7 @@ import com.android.server.webkit.WebViewUpdateService; import com.android.server.wm.ActivityTaskManagerService; import com.android.server.wm.WindowManagerGlobalLock; import com.android.server.wm.WindowManagerService; import com.google.android.startop.iorap.IorapForwardingService; import dalvik.system.VMRuntime; Loading Loading @@ -1007,10 +1008,13 @@ public final class SystemServer { mSystemServiceManager.startService(PinnerService.class); traceEnd(); traceBeginAndSlog("IorapForwardingService"); mSystemServiceManager.startService(IorapForwardingService.class); traceEnd(); traceBeginAndSlog("SignedConfigService"); SignedConfigService.registerUpdateReceiver(mSystemContext); traceEnd(); } catch (RuntimeException e) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting core service", e); Loading
services/startop/Android.bp 0 → 100644 +24 −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. */ java_library_static { name: "services.startop", static_libs: [ // frameworks/base/startop/iorap "services.startop.iorap", ], }
startop/iorap/Android.bp +3 −1 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ // limitations under the License. java_library_static { name: "libiorap-java", name: "services.startop.iorap", aidl: { include_dirs: [ Loading @@ -21,6 +21,8 @@ java_library_static { ], }, libs: ["services.core"], srcs: [ ":iorap-aidl", "**/*.java", Loading
startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java 0 → 100644 +368 −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.google.android.startop.iorap; import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Parcel; import android.os.Parcelable; // TODO: fix this. either move this class into system server or add a dependency on // these wm classes to libiorap-java and libiorap-java-tests (somehow). import com.android.server.wm.ActivityMetricsLaunchObserver; import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto; import com.android.server.wm.ActivityMetricsLaunchObserver.Temperature; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.InvocationTargetException; import java.util.Objects; /** * Provide a hint to iorapd that an app launch sequence has transitioned state.<br /><br /> * * Knowledge of when an activity starts/stops can be used by iorapd to increase system * performance (e.g. by launching perfetto tracing to record an io profile, or by * playing back an ioprofile via readahead) over the long run.<br /><br /> * * /@see com.google.android.startop.iorap.IIorap#onAppLaunchEvent <br /><br /> * @see com.android.server.wm.ActivityMetricsLaunchObserver * ActivityMetricsLaunchObserver for the possible event states. * @hide */ public abstract class AppLaunchEvent implements Parcelable { @LongDef @Retention(RetentionPolicy.SOURCE) public @interface SequenceId {} public final @SequenceId long sequenceId; protected AppLaunchEvent(@SequenceId long sequenceId) { this.sequenceId = sequenceId; } @Override public boolean equals(Object other) { if (other instanceof AppLaunchEvent) { return equals((AppLaunchEvent) other); } return false; } protected boolean equals(AppLaunchEvent other) { return sequenceId == other.sequenceId; } @Override public String toString() { return getClass().getSimpleName() + "{" + "sequenceId=" + Long.toString(sequenceId) + toStringBody() + "}"; } protected String toStringBody() { return ""; }; // List of possible variants: public static final class IntentStarted extends AppLaunchEvent { @NonNull public final Intent intent; public IntentStarted(@SequenceId long sequenceId, Intent intent) { super(sequenceId); this.intent = intent; Objects.requireNonNull(intent, "intent"); } @Override public boolean equals(Object other) { if (other instanceof IntentStarted) { return intent.equals(((IntentStarted)other).intent) && super.equals(other); } return false; } @Override protected String toStringBody() { return ", intent=" + intent.toString(); } @Override protected void writeToParcelImpl(Parcel p, int flags) { super.writeToParcelImpl(p, flags); intent.writeToParcel(p, flags); } IntentStarted(Parcel p) { super(p); intent = Intent.CREATOR.createFromParcel(p); } } public static final class IntentFailed extends AppLaunchEvent { public IntentFailed(@SequenceId long sequenceId) { super(sequenceId); } @Override public boolean equals(Object other) { if (other instanceof IntentFailed) { return super.equals(other); } return false; } IntentFailed(Parcel p) { super(p); } } public static abstract class BaseWithActivityRecordData extends AppLaunchEvent { public final @NonNull @ActivityRecordProto byte[] activityRecordSnapshot; protected BaseWithActivityRecordData(@SequenceId long sequenceId, @NonNull @ActivityRecordProto byte[] snapshot) { super(sequenceId); activityRecordSnapshot = snapshot; Objects.requireNonNull(snapshot, "snapshot"); } @Override public boolean equals(Object other) { if (other instanceof BaseWithActivityRecordData) { return activityRecordSnapshot.equals( ((BaseWithActivityRecordData)other).activityRecordSnapshot) && super.equals(other); } return false; } @Override protected String toStringBody() { return ", " + activityRecordSnapshot.toString(); } @Override protected void writeToParcelImpl(Parcel p, int flags) { super.writeToParcelImpl(p, flags); ActivityRecordProtoParcelable.write(p, activityRecordSnapshot, flags); } BaseWithActivityRecordData(Parcel p) { super(p); activityRecordSnapshot = ActivityRecordProtoParcelable.create(p); } } public static final class ActivityLaunched extends BaseWithActivityRecordData { public final @ActivityMetricsLaunchObserver.Temperature int temperature; public ActivityLaunched(@SequenceId long sequenceId, @NonNull @ActivityRecordProto byte[] snapshot, @ActivityMetricsLaunchObserver.Temperature int temperature) { super(sequenceId, snapshot); this.temperature = temperature; } @Override public boolean equals(Object other) { if (other instanceof ActivityLaunched) { return temperature == ((ActivityLaunched)other).temperature && super.equals(other); } return false; } @Override protected String toStringBody() { return ", temperature=" + Integer.toString(temperature); } @Override protected void writeToParcelImpl(Parcel p, int flags) { super.writeToParcelImpl(p, flags); p.writeInt(temperature); } ActivityLaunched(Parcel p) { super(p); temperature = p.readInt(); } } public static final class ActivityLaunchFinished extends BaseWithActivityRecordData { public ActivityLaunchFinished(@SequenceId long sequenceId, @NonNull @ActivityRecordProto byte[] snapshot) { super(sequenceId, snapshot); } @Override public boolean equals(Object other) { if (other instanceof ActivityLaunched) { return super.equals(other); } return false; } } public static class ActivityLaunchCancelled extends AppLaunchEvent { public final @Nullable @ActivityRecordProto byte[] activityRecordSnapshot; public ActivityLaunchCancelled(@SequenceId long sequenceId, @Nullable @ActivityRecordProto byte[] snapshot) { super(sequenceId); activityRecordSnapshot = snapshot; } @Override public boolean equals(Object other) { if (other instanceof ActivityLaunchCancelled) { return Objects.equals(activityRecordSnapshot, ((ActivityLaunchCancelled)other).activityRecordSnapshot) && super.equals(other); } return false; } @Override protected String toStringBody() { return ", " + activityRecordSnapshot.toString(); } @Override protected void writeToParcelImpl(Parcel p, int flags) { super.writeToParcelImpl(p, flags); if (activityRecordSnapshot != null) { p.writeBoolean(true); ActivityRecordProtoParcelable.write(p, activityRecordSnapshot, flags); } else { p.writeBoolean(false); } } ActivityLaunchCancelled(Parcel p) { super(p); if (p.readBoolean()) { activityRecordSnapshot = ActivityRecordProtoParcelable.create(p); } else { activityRecordSnapshot = null; } } } @Override public @ContentsFlags int describeContents() { return 0; } @Override public void writeToParcel(Parcel p, @WriteFlags int flags) { p.writeInt(getTypeIndex()); writeToParcelImpl(p, flags); } public static Creator<AppLaunchEvent> CREATOR = new Creator<AppLaunchEvent>() { @Override public AppLaunchEvent createFromParcel(Parcel source) { int typeIndex = source.readInt(); Class<?> kls = getClassFromTypeIndex(typeIndex); if (kls == null) { throw new IllegalArgumentException("Invalid type index: " + typeIndex); } try { return (AppLaunchEvent) kls.getConstructor(Parcel.class).newInstance(source); } catch (InstantiationException e) { throw new AssertionError(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } @Override public AppLaunchEvent[] newArray(int size) { return new AppLaunchEvent[0]; } }; protected void writeToParcelImpl(Parcel p, int flags) { p.writeLong(sequenceId); } protected AppLaunchEvent(Parcel p) { sequenceId = p.readLong(); } private int getTypeIndex() { for (int i = 0; i < sTypes.length; ++i) { if (sTypes[i].equals(this.getClass())) { return i; } } throw new AssertionError("sTypes did not include this type: " + this.getClass()); } private static @Nullable Class<?> getClassFromTypeIndex(int typeIndex) { if (typeIndex >= 0 && typeIndex < sTypes.length) { return sTypes[typeIndex]; } return null; } // Index position matters: It is used to encode the specific type in parceling. // Keep up-to-date with C++ side. private static Class<?>[] sTypes = new Class[] { IntentStarted.class, IntentFailed.class, ActivityLaunched.class, ActivityLaunchFinished.class, ActivityLaunchCancelled.class, }; // TODO: move to @ActivityRecordProto byte[] once we have unit tests. public static class ActivityRecordProtoParcelable { public static void write(Parcel p, @ActivityRecordProto byte[] activityRecordSnapshot, int flags) { p.writeByteArray(activityRecordSnapshot); } public static @ActivityRecordProto byte[] create(Parcel p) { byte[] data = p.createByteArray(); return data; } } }