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

Commit c7da33de authored by Shin Kawamura's avatar Shin Kawamura
Browse files

add ZramMaintenance

ZramMaintenance asks mmd to run zram maintenance (e.g. zram writeback,
zram recompression).

Bug: 375432472
Test: manual
Flag: android.mmd.flags.mmd_enabled

Change-Id: I0c451188909d11afd02af6662c0080dc6218710f
parent 8664e205
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -9273,6 +9273,11 @@
                android:permission="android.permission.BIND_JOB_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"
                 android:exported="false"
                 android:permission="android.permission.BIND_JOB_SERVICE" >
+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ filegroup {
        ":framework_native_aidl",
        ":gsiservice_aidl",
        ":installd_aidl",
        ":mmd_aidl",
        ":storaged_aidl",
        ":vold_aidl",
    ],
@@ -245,6 +246,7 @@ java_library_static {
        "aconfig_new_storage_flags_lib",
        "powerstats_flags_lib",
        "locksettings_flags_lib",
        "mmd_flags_lib",
        "profiling_flags_lib",
        "android.adpf.sessionmanager_aidl-java",
        "uprobestats_flags_java_lib",
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ per-file DisplayThread.java = michaelwr@google.com, ogunwale@google.com

# Zram writeback
per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com
per-file ZramMaintenance.java = kawasin@google.com

# ServiceWatcher
per-file ServiceWatcher.java = sooniln@google.com
+12 −6
Original line number Diff line number Diff line
@@ -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.MOUNTED;
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.writeStringAttribute;
@@ -945,6 +946,10 @@ class StorageManagerService extends IStorageManager.Stub
            });
        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
            String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
            if (!zramPropValue.equals("0")
@@ -952,6 +957,7 @@ class StorageManagerService extends IStorageManager.Stub
                    com.android.internal.R.bool.config_zramWriteback)) {
                ZramWriteback.scheduleZramWriteback(mContext);
            }
        }

        configureTranscoding();
    }
@@ -977,7 +983,7 @@ class StorageManagerService extends IStorageManager.Stub
            // sole writer.
            SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue);
            // Schedule writeback only if zram is being enabled.
            if (desiredPropertyValue.equals("1")
            if (!mmdEnabled() && desiredPropertyValue.equals("1")
                    && mContext.getResources().getBoolean(
                        com.android.internal.R.bool.config_zramWriteback)) {
                ZramWriteback.scheduleZramWriteback(mContext);
+118 −0
Original line number 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());
        }
    }
}