Loading core/res/AndroidManifest.xml +5 −0 Original line number Original line Diff line number Diff line Loading @@ -9272,6 +9272,11 @@ android:permission="android.permission.BIND_JOB_SERVICE" > android:permission="android.permission.BIND_JOB_SERVICE" > </service> </service> <service android:name="com.android.server.ZramMaintenance" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" > </service> <service android:name="com.android.server.ZramWriteback" <service android:name="com.android.server.ZramWriteback" android:exported="false" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" > android:permission="android.permission.BIND_JOB_SERVICE" > Loading services/core/Android.bp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,7 @@ filegroup { ":framework_native_aidl", ":framework_native_aidl", ":gsiservice_aidl", ":gsiservice_aidl", ":installd_aidl", ":installd_aidl", ":mmd_aidl", ":storaged_aidl", ":storaged_aidl", ":vold_aidl", ":vold_aidl", ], ], Loading Loading @@ -246,6 +247,7 @@ java_library_static { "aconfig_new_storage_flags_lib", "aconfig_new_storage_flags_lib", "powerstats_flags_lib", "powerstats_flags_lib", "locksettings_flags_lib", "locksettings_flags_lib", "mmd_flags_lib", "profiling_flags_lib", "profiling_flags_lib", "android.adpf.sessionmanager_aidl-java", "android.adpf.sessionmanager_aidl-java", "uprobestats_flags_java_lib", "uprobestats_flags_java_lib", Loading services/core/java/com/android/server/OWNERS +1 −0 Original line number Original line Diff line number Diff line Loading @@ -9,6 +9,7 @@ per-file DisplayThread.java = michaelwr@google.com, ogunwale@google.com # Zram writeback # Zram writeback per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com per-file ZramMaintenance.java = kawasin@google.com # ServiceWatcher # ServiceWatcher per-file ServiceWatcher.java = sooniln@google.com per-file ServiceWatcher.java = sooniln@google.com Loading services/core/java/com/android/server/StorageManagerService.java +12 −6 Original line number Original line Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED; import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED; import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED; import static android.os.storage.OnObbStateChangeListener.MOUNTED; import static android.os.storage.OnObbStateChangeListener.MOUNTED; import static android.os.storage.OnObbStateChangeListener.UNMOUNTED; import static android.os.storage.OnObbStateChangeListener.UNMOUNTED; import static android.mmd.flags.Flags.mmdEnabled; import static com.android.internal.util.XmlUtils.readStringAttribute; import static com.android.internal.util.XmlUtils.readStringAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; Loading Loading @@ -945,6 +946,10 @@ class StorageManagerService extends IStorageManager.Stub }); }); refreshZramSettings(); refreshZramSettings(); if (mmdEnabled()) { // TODO: b/375432472 - Start zram maintenance only when zram is enabled. ZramMaintenance.startZramMaintenance(mContext); } else { // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); if (!zramPropValue.equals("0") if (!zramPropValue.equals("0") Loading @@ -952,6 +957,7 @@ class StorageManagerService extends IStorageManager.Stub com.android.internal.R.bool.config_zramWriteback)) { com.android.internal.R.bool.config_zramWriteback)) { ZramWriteback.scheduleZramWriteback(mContext); ZramWriteback.scheduleZramWriteback(mContext); } } } configureTranscoding(); configureTranscoding(); } } Loading @@ -977,7 +983,7 @@ class StorageManagerService extends IStorageManager.Stub // sole writer. // sole writer. SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue); SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue); // Schedule writeback only if zram is being enabled. // Schedule writeback only if zram is being enabled. if (desiredPropertyValue.equals("1") if (!mmdEnabled() && desiredPropertyValue.equals("1") && mContext.getResources().getBoolean( && mContext.getResources().getBoolean( com.android.internal.R.bool.config_zramWriteback)) { com.android.internal.R.bool.config_zramWriteback)) { ZramWriteback.scheduleZramWriteback(mContext); ZramWriteback.scheduleZramWriteback(mContext); Loading services/core/java/com/android/server/ZramMaintenance.java 0 → 100644 +118 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2024 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; import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobService; import android.content.ComponentName; import android.content.Context; import android.os.IBinder; import android.os.IMmd; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.util.Slog; import java.time.Duration; /** * Schedules zram maintenance (e.g. zram writeback, zram recompression). * * <p>ZramMaintenance notifies mmd the good timing to execute zram maintenance based on: * * <ul> * <li>Enough interval has passed. * <li>The system is idle. * <li>The battery is not low. * </ul> */ public class ZramMaintenance extends JobService { private static final String TAG = ZramMaintenance.class.getName(); // Job id must be unique across all clients of the same uid. ZramMaintenance uses the bug number // as the job id. private static final int JOB_ID = 375432472; private static final ComponentName sZramMaintenance = new ComponentName("android", ZramMaintenance.class.getName()); private static final String FIRST_DELAY_SECONDS_PROP = "mm.zram.maintenance.first_delay_seconds"; // The default is 1 hour. private static final long DEFAULT_FIRST_DELAY_SECONDS = 3600; private static final String PERIODIC_DELAY_SECONDS_PROP = "mm.zram.maintenance.periodic_delay_seconds"; // The default is 1 hour. private static final long DEFAULT_PERIODIC_DELAY_SECONDS = 3600; private static final String REQUIRE_DEVICE_IDLE_PROP = "mm.zram.maintenance.require_device_idle"; private static final boolean DEFAULT_REQUIRE_DEVICE_IDLE = true; private static final String REQUIRE_BATTERY_NOT_LOW_PROP = "mm.zram.maintenance.require_battry_not_low"; private static final boolean DEFAULT_REQUIRE_BATTERY_NOT_LOW = true; @Override public boolean onStartJob(JobParameters params) { IBinder binder = ServiceManager.getService("mmd"); if (binder != null) { IMmd mmd = IMmd.Stub.asInterface(binder); try { mmd.doZramMaintenance(); } catch (RemoteException e) { Slog.e(TAG, "Failed to doZramMaintenance", e); } } else { Slog.w(TAG, "binder not found"); } Duration delay = Duration.ofSeconds(SystemProperties.getLong(PERIODIC_DELAY_SECONDS_PROP, DEFAULT_PERIODIC_DELAY_SECONDS)); scheduleZramMaintenance(this, delay); return true; } @Override public boolean onStopJob(JobParameters params) { return false; } /** * Starts periodical zram maintenance. */ public static void startZramMaintenance(Context context) { Duration delay = Duration.ofSeconds( SystemProperties.getLong(FIRST_DELAY_SECONDS_PROP, DEFAULT_FIRST_DELAY_SECONDS)); scheduleZramMaintenance(context, delay); } private static void scheduleZramMaintenance(Context context, Duration delay) { JobScheduler js = context.getSystemService(JobScheduler.class); if (js != null) { js.schedule(new JobInfo.Builder(JOB_ID, sZramMaintenance) .setMinimumLatency(delay.toMillis()) .setRequiresDeviceIdle( SystemProperties.getBoolean(REQUIRE_DEVICE_IDLE_PROP, DEFAULT_REQUIRE_DEVICE_IDLE)) .setRequiresBatteryNotLow( SystemProperties.getBoolean(REQUIRE_BATTERY_NOT_LOW_PROP, DEFAULT_REQUIRE_BATTERY_NOT_LOW)) .build()); } } } Loading
core/res/AndroidManifest.xml +5 −0 Original line number Original line Diff line number Diff line Loading @@ -9272,6 +9272,11 @@ android:permission="android.permission.BIND_JOB_SERVICE" > android:permission="android.permission.BIND_JOB_SERVICE" > </service> </service> <service android:name="com.android.server.ZramMaintenance" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" > </service> <service android:name="com.android.server.ZramWriteback" <service android:name="com.android.server.ZramWriteback" android:exported="false" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" > android:permission="android.permission.BIND_JOB_SERVICE" > Loading
services/core/Android.bp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -37,6 +37,7 @@ filegroup { ":framework_native_aidl", ":framework_native_aidl", ":gsiservice_aidl", ":gsiservice_aidl", ":installd_aidl", ":installd_aidl", ":mmd_aidl", ":storaged_aidl", ":storaged_aidl", ":vold_aidl", ":vold_aidl", ], ], Loading Loading @@ -246,6 +247,7 @@ java_library_static { "aconfig_new_storage_flags_lib", "aconfig_new_storage_flags_lib", "powerstats_flags_lib", "powerstats_flags_lib", "locksettings_flags_lib", "locksettings_flags_lib", "mmd_flags_lib", "profiling_flags_lib", "profiling_flags_lib", "android.adpf.sessionmanager_aidl-java", "android.adpf.sessionmanager_aidl-java", "uprobestats_flags_java_lib", "uprobestats_flags_java_lib", Loading
services/core/java/com/android/server/OWNERS +1 −0 Original line number Original line Diff line number Diff line Loading @@ -9,6 +9,7 @@ per-file DisplayThread.java = michaelwr@google.com, ogunwale@google.com # Zram writeback # Zram writeback per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com per-file ZramMaintenance.java = kawasin@google.com # ServiceWatcher # ServiceWatcher per-file ServiceWatcher.java = sooniln@google.com per-file ServiceWatcher.java = sooniln@google.com Loading
services/core/java/com/android/server/StorageManagerService.java +12 −6 Original line number Original line Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static android.os.storage.OnObbStateChangeListener.ERROR_NOT_MOUNTED; import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED; import static android.os.storage.OnObbStateChangeListener.ERROR_PERMISSION_DENIED; import static android.os.storage.OnObbStateChangeListener.MOUNTED; import static android.os.storage.OnObbStateChangeListener.MOUNTED; import static android.os.storage.OnObbStateChangeListener.UNMOUNTED; import static android.os.storage.OnObbStateChangeListener.UNMOUNTED; import static android.mmd.flags.Flags.mmdEnabled; import static com.android.internal.util.XmlUtils.readStringAttribute; import static com.android.internal.util.XmlUtils.readStringAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; Loading Loading @@ -945,6 +946,10 @@ class StorageManagerService extends IStorageManager.Stub }); }); refreshZramSettings(); refreshZramSettings(); if (mmdEnabled()) { // TODO: b/375432472 - Start zram maintenance only when zram is enabled. ZramMaintenance.startZramMaintenance(mContext); } else { // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); if (!zramPropValue.equals("0") if (!zramPropValue.equals("0") Loading @@ -952,6 +957,7 @@ class StorageManagerService extends IStorageManager.Stub com.android.internal.R.bool.config_zramWriteback)) { com.android.internal.R.bool.config_zramWriteback)) { ZramWriteback.scheduleZramWriteback(mContext); ZramWriteback.scheduleZramWriteback(mContext); } } } configureTranscoding(); configureTranscoding(); } } Loading @@ -977,7 +983,7 @@ class StorageManagerService extends IStorageManager.Stub // sole writer. // sole writer. SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue); SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue); // Schedule writeback only if zram is being enabled. // Schedule writeback only if zram is being enabled. if (desiredPropertyValue.equals("1") if (!mmdEnabled() && desiredPropertyValue.equals("1") && mContext.getResources().getBoolean( && mContext.getResources().getBoolean( com.android.internal.R.bool.config_zramWriteback)) { com.android.internal.R.bool.config_zramWriteback)) { ZramWriteback.scheduleZramWriteback(mContext); ZramWriteback.scheduleZramWriteback(mContext); Loading
services/core/java/com/android/server/ZramMaintenance.java 0 → 100644 +118 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2024 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; import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobService; import android.content.ComponentName; import android.content.Context; import android.os.IBinder; import android.os.IMmd; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.util.Slog; import java.time.Duration; /** * Schedules zram maintenance (e.g. zram writeback, zram recompression). * * <p>ZramMaintenance notifies mmd the good timing to execute zram maintenance based on: * * <ul> * <li>Enough interval has passed. * <li>The system is idle. * <li>The battery is not low. * </ul> */ public class ZramMaintenance extends JobService { private static final String TAG = ZramMaintenance.class.getName(); // Job id must be unique across all clients of the same uid. ZramMaintenance uses the bug number // as the job id. private static final int JOB_ID = 375432472; private static final ComponentName sZramMaintenance = new ComponentName("android", ZramMaintenance.class.getName()); private static final String FIRST_DELAY_SECONDS_PROP = "mm.zram.maintenance.first_delay_seconds"; // The default is 1 hour. private static final long DEFAULT_FIRST_DELAY_SECONDS = 3600; private static final String PERIODIC_DELAY_SECONDS_PROP = "mm.zram.maintenance.periodic_delay_seconds"; // The default is 1 hour. private static final long DEFAULT_PERIODIC_DELAY_SECONDS = 3600; private static final String REQUIRE_DEVICE_IDLE_PROP = "mm.zram.maintenance.require_device_idle"; private static final boolean DEFAULT_REQUIRE_DEVICE_IDLE = true; private static final String REQUIRE_BATTERY_NOT_LOW_PROP = "mm.zram.maintenance.require_battry_not_low"; private static final boolean DEFAULT_REQUIRE_BATTERY_NOT_LOW = true; @Override public boolean onStartJob(JobParameters params) { IBinder binder = ServiceManager.getService("mmd"); if (binder != null) { IMmd mmd = IMmd.Stub.asInterface(binder); try { mmd.doZramMaintenance(); } catch (RemoteException e) { Slog.e(TAG, "Failed to doZramMaintenance", e); } } else { Slog.w(TAG, "binder not found"); } Duration delay = Duration.ofSeconds(SystemProperties.getLong(PERIODIC_DELAY_SECONDS_PROP, DEFAULT_PERIODIC_DELAY_SECONDS)); scheduleZramMaintenance(this, delay); return true; } @Override public boolean onStopJob(JobParameters params) { return false; } /** * Starts periodical zram maintenance. */ public static void startZramMaintenance(Context context) { Duration delay = Duration.ofSeconds( SystemProperties.getLong(FIRST_DELAY_SECONDS_PROP, DEFAULT_FIRST_DELAY_SECONDS)); scheduleZramMaintenance(context, delay); } private static void scheduleZramMaintenance(Context context, Duration delay) { JobScheduler js = context.getSystemService(JobScheduler.class); if (js != null) { js.schedule(new JobInfo.Builder(JOB_ID, sZramMaintenance) .setMinimumLatency(delay.toMillis()) .setRequiresDeviceIdle( SystemProperties.getBoolean(REQUIRE_DEVICE_IDLE_PROP, DEFAULT_REQUIRE_DEVICE_IDLE)) .setRequiresBatteryNotLow( SystemProperties.getBoolean(REQUIRE_BATTERY_NOT_LOW_PROP, DEFAULT_REQUIRE_BATTERY_NOT_LOW)) .build()); } } }