From 849150a13c322f9968907d37b79afbd50ef270bd Mon Sep 17 00:00:00 2001 From: Shintaro Kawamura Date: Fri, 31 Jan 2025 12:24:42 +0900 Subject: Move ZramMaintenance to com.android.server.memory package classes in services/core/java/com/android/server should be in the same structure as the tests. This is to align ZramMaintenance.java and ZramMaintenanceTest.kt in the same structure. We don't change ZramWriteback.java for a backward compatibility. Bug: 375432472 Test: m && atest FrameworksServicesTests:ZramMaintenanceTest Change-Id: Ib1eb07e388ffe010bfa1e62349b05ea6fc02d63d --- core/res/AndroidManifest.xml | 2 +- services/core/java/com/android/server/OWNERS | 1 - .../com/android/server/StorageManagerService.java | 1 + .../java/com/android/server/ZramMaintenance.java | 172 --------------------- .../core/java/com/android/server/memory/OWNERS | 3 + .../com/android/server/memory/ZramMaintenance.java | 172 +++++++++++++++++++++ .../src/com/android/server/memory/OWNERS | 3 + .../android/server/memory/ZramMaintenanceTest.kt | 154 ++++++++++++++++++ .../com/android/server/zram/ZramMaintenanceTest.kt | 155 ------------------- 9 files changed, 334 insertions(+), 329 deletions(-) delete mode 100644 services/core/java/com/android/server/ZramMaintenance.java create mode 100644 services/core/java/com/android/server/memory/OWNERS create mode 100644 services/core/java/com/android/server/memory/ZramMaintenance.java create mode 100644 services/tests/servicestests/src/com/android/server/memory/OWNERS create mode 100644 services/tests/servicestests/src/com/android/server/memory/ZramMaintenanceTest.kt delete mode 100644 services/tests/servicestests/src/com/android/server/zram/ZramMaintenanceTest.kt diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 45c4ea08c09b..c084bdda5c01 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -8910,7 +8910,7 @@ android:permission="android.permission.BIND_JOB_SERVICE" > - diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index ef769cf6217c..6858e2941ff9 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -9,7 +9,6 @@ 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 diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 6045f63439f3..441fe4f7723c 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -155,6 +155,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; +import com.android.server.memory.ZramMaintenance; import com.android.server.pm.Installer; import com.android.server.pm.UserManagerInternal; import com.android.server.storage.AppFuseBridge; diff --git a/services/core/java/com/android/server/ZramMaintenance.java b/services/core/java/com/android/server/ZramMaintenance.java deleted file mode 100644 index 099e5b3fe440..000000000000 --- a/services/core/java/com/android/server/ZramMaintenance.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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.PersistableBundle; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemProperties; -import android.provider.DeviceConfig; -import android.util.Slog; - -import com.android.internal.annotations.VisibleForTesting; - -import java.time.Duration; - -/** - * Schedules zram maintenance (e.g. zram writeback, zram recompression). - * - *

ZramMaintenance notifies mmd the good timing to execute zram maintenance based on: - * - *

- */ -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. - @VisibleForTesting - public static final int JOB_ID = 375432472; - private static final ComponentName sZramMaintenance = - new ComponentName("android", ZramMaintenance.class.getName()); - @VisibleForTesting - public static final String KEY_CHECK_STATUS = "check_status"; - - private static final String SYSTEM_PROPERTY_PREFIX = "mm."; - private static final String FIRST_DELAY_SECONDS_PROP = - "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 = - "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 = - "zram.maintenance.require_device_idle"; - private static final boolean DEFAULT_REQUIRE_DEVICE_IDLE = - true; - private static final String REQUIRE_BATTERY_NOT_LOW_PROP = - "zram.maintenance.require_battry_not_low"; - private static final boolean DEFAULT_REQUIRE_BATTERY_NOT_LOW = - true; - - @Override - public boolean onStartJob(JobParameters params) { - new Thread("ZramMaintenance") { - @Override - public void run() { - try { - IBinder binder = ServiceManager.getService("mmd"); - IMmd mmd = IMmd.Stub.asInterface(binder); - startJob(ZramMaintenance.this, params, mmd); - } finally { - jobFinished(params, false); - } - } - }.start(); - return true; - } - - @Override - public boolean onStopJob(JobParameters params) { - return false; - } - - /** - * This is public to test ZramMaintenance logic. - * - *

- * We need to pass mmd as parameter because we can't mock "IMmd.Stub.asInterface". - * - *

- * Since IMmd.isZramMaintenanceSupported() is blocking call, this method should be executed on - * a worker thread. - */ - @VisibleForTesting - public static void startJob(Context context, JobParameters params, IMmd mmd) { - boolean checkStatus = params.getExtras().getBoolean(KEY_CHECK_STATUS); - if (mmd != null) { - try { - if (checkStatus && !mmd.isZramMaintenanceSupported()) { - Slog.i(TAG, "zram maintenance is not supported"); - return; - } - // Status check is required before the first doZramMaintenanceAsync() call once. - checkStatus = false; - - mmd.doZramMaintenanceAsync(); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to binder call to mmd", e); - } - } else { - Slog.w(TAG, "binder not found"); - } - Duration delay = Duration.ofSeconds(getLongProperty(PERIODIC_DELAY_SECONDS_PROP, - DEFAULT_PERIODIC_DELAY_SECONDS)); - scheduleZramMaintenance(context, delay, checkStatus); - } - - /** - * Starts periodical zram maintenance. - */ - public static void startZramMaintenance(Context context) { - Duration delay = Duration.ofSeconds( - getLongProperty(FIRST_DELAY_SECONDS_PROP, DEFAULT_FIRST_DELAY_SECONDS)); - scheduleZramMaintenance(context, delay, true); - } - - private static void scheduleZramMaintenance(Context context, Duration delay, - boolean checkStatus) { - JobScheduler js = context.getSystemService(JobScheduler.class); - - if (js != null) { - final PersistableBundle bundle = new PersistableBundle(); - bundle.putBoolean(KEY_CHECK_STATUS, checkStatus); - js.schedule(new JobInfo.Builder(JOB_ID, sZramMaintenance) - .setMinimumLatency(delay.toMillis()) - .setRequiresDeviceIdle( - getBooleanProperty(REQUIRE_DEVICE_IDLE_PROP, - DEFAULT_REQUIRE_DEVICE_IDLE)) - .setRequiresBatteryNotLow( - getBooleanProperty(REQUIRE_BATTERY_NOT_LOW_PROP, - DEFAULT_REQUIRE_BATTERY_NOT_LOW)) - .setExtras(bundle) - .build()); - } - } - - private static long getLongProperty(String name, long defaultValue) { - return DeviceConfig.getLong(DeviceConfig.NAMESPACE_MM, name, - SystemProperties.getLong(SYSTEM_PROPERTY_PREFIX + name, defaultValue)); - } - - private static boolean getBooleanProperty(String name, boolean defaultValue) { - return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_MM, name, - SystemProperties.getBoolean(SYSTEM_PROPERTY_PREFIX + name, defaultValue)); - } -} diff --git a/services/core/java/com/android/server/memory/OWNERS b/services/core/java/com/android/server/memory/OWNERS new file mode 100644 index 000000000000..dc0e89892e43 --- /dev/null +++ b/services/core/java/com/android/server/memory/OWNERS @@ -0,0 +1,3 @@ +include /MEMORY_OWNERS + +per-file ZramMaintenance.java = kawasin@google.com diff --git a/services/core/java/com/android/server/memory/ZramMaintenance.java b/services/core/java/com/android/server/memory/ZramMaintenance.java new file mode 100644 index 000000000000..48358d130987 --- /dev/null +++ b/services/core/java/com/android/server/memory/ZramMaintenance.java @@ -0,0 +1,172 @@ +/* + * 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.memory; + +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.PersistableBundle; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemProperties; +import android.provider.DeviceConfig; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; + +import java.time.Duration; + +/** + * Schedules zram maintenance (e.g. zram writeback, zram recompression). + * + *

ZramMaintenance notifies mmd the good timing to execute zram maintenance based on: + * + *

+ */ +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. + @VisibleForTesting + public static final int JOB_ID = 375432472; + private static final ComponentName sZramMaintenance = + new ComponentName("android", ZramMaintenance.class.getName()); + @VisibleForTesting + public static final String KEY_CHECK_STATUS = "check_status"; + + private static final String SYSTEM_PROPERTY_PREFIX = "mm."; + private static final String FIRST_DELAY_SECONDS_PROP = + "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 = + "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 = + "zram.maintenance.require_device_idle"; + private static final boolean DEFAULT_REQUIRE_DEVICE_IDLE = + true; + private static final String REQUIRE_BATTERY_NOT_LOW_PROP = + "zram.maintenance.require_battry_not_low"; + private static final boolean DEFAULT_REQUIRE_BATTERY_NOT_LOW = + true; + + @Override + public boolean onStartJob(JobParameters params) { + new Thread("ZramMaintenance") { + @Override + public void run() { + try { + IBinder binder = ServiceManager.getService("mmd"); + IMmd mmd = IMmd.Stub.asInterface(binder); + startJob(ZramMaintenance.this, params, mmd); + } finally { + jobFinished(params, false); + } + } + }.start(); + return true; + } + + @Override + public boolean onStopJob(JobParameters params) { + return false; + } + + /** + * This is public to test ZramMaintenance logic. + * + *

+ * We need to pass mmd as parameter because we can't mock "IMmd.Stub.asInterface". + * + *

+ * Since IMmd.isZramMaintenanceSupported() is blocking call, this method should be executed on + * a worker thread. + */ + @VisibleForTesting + public static void startJob(Context context, JobParameters params, IMmd mmd) { + boolean checkStatus = params.getExtras().getBoolean(KEY_CHECK_STATUS); + if (mmd != null) { + try { + if (checkStatus && !mmd.isZramMaintenanceSupported()) { + Slog.i(TAG, "zram maintenance is not supported"); + return; + } + // Status check is required before the first doZramMaintenanceAsync() call once. + checkStatus = false; + + mmd.doZramMaintenanceAsync(); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to binder call to mmd", e); + } + } else { + Slog.w(TAG, "binder not found"); + } + Duration delay = Duration.ofSeconds(getLongProperty(PERIODIC_DELAY_SECONDS_PROP, + DEFAULT_PERIODIC_DELAY_SECONDS)); + scheduleZramMaintenance(context, delay, checkStatus); + } + + /** + * Starts periodical zram maintenance. + */ + public static void startZramMaintenance(Context context) { + Duration delay = Duration.ofSeconds( + getLongProperty(FIRST_DELAY_SECONDS_PROP, DEFAULT_FIRST_DELAY_SECONDS)); + scheduleZramMaintenance(context, delay, true); + } + + private static void scheduleZramMaintenance(Context context, Duration delay, + boolean checkStatus) { + JobScheduler js = context.getSystemService(JobScheduler.class); + + if (js != null) { + final PersistableBundle bundle = new PersistableBundle(); + bundle.putBoolean(KEY_CHECK_STATUS, checkStatus); + js.schedule(new JobInfo.Builder(JOB_ID, sZramMaintenance) + .setMinimumLatency(delay.toMillis()) + .setRequiresDeviceIdle( + getBooleanProperty(REQUIRE_DEVICE_IDLE_PROP, + DEFAULT_REQUIRE_DEVICE_IDLE)) + .setRequiresBatteryNotLow( + getBooleanProperty(REQUIRE_BATTERY_NOT_LOW_PROP, + DEFAULT_REQUIRE_BATTERY_NOT_LOW)) + .setExtras(bundle) + .build()); + } + } + + private static long getLongProperty(String name, long defaultValue) { + return DeviceConfig.getLong(DeviceConfig.NAMESPACE_MM, name, + SystemProperties.getLong(SYSTEM_PROPERTY_PREFIX + name, defaultValue)); + } + + private static boolean getBooleanProperty(String name, boolean defaultValue) { + return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_MM, name, + SystemProperties.getBoolean(SYSTEM_PROPERTY_PREFIX + name, defaultValue)); + } +} diff --git a/services/tests/servicestests/src/com/android/server/memory/OWNERS b/services/tests/servicestests/src/com/android/server/memory/OWNERS new file mode 100644 index 000000000000..4df08c1fbc2e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/memory/OWNERS @@ -0,0 +1,3 @@ +include /MEMORY_OWNERS + +per-file ZramMaintenanceTest.kt = kawasin@google.com diff --git a/services/tests/servicestests/src/com/android/server/memory/ZramMaintenanceTest.kt b/services/tests/servicestests/src/com/android/server/memory/ZramMaintenanceTest.kt new file mode 100644 index 000000000000..1f59f45b05bf --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/memory/ZramMaintenanceTest.kt @@ -0,0 +1,154 @@ +/* + * 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.memory + +import android.app.job.JobInfo +import android.app.job.JobParameters +import android.app.job.JobScheduler +import android.os.IMmd +import android.os.PersistableBundle +import android.os.RemoteException +import android.testing.TestableContext +import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry + +import com.google.common.truth.Truth.assertThat + +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.ArgumentCaptor +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations + +private fun generateJobParameters(jobId: Int, extras: PersistableBundle): JobParameters { + return JobParameters( + null, "", jobId, extras, null, null, 0, false, false, false, null, null, null + ) +} + +@SmallTest +@RunWith(JUnit4::class) +class ZramMaintenanceTest { + private val context = TestableContext(InstrumentationRegistry.getInstrumentation().context) + + @Captor + private lateinit var jobInfoCaptor: ArgumentCaptor + + @Mock + private lateinit var mockJobScheduler: JobScheduler + + @Mock + private lateinit var mockMmd: IMmd + + @Before + @Throws(RemoteException::class) + fun setUp() { + MockitoAnnotations.initMocks(this) + context.addMockSystemService(JobScheduler::class.java, mockJobScheduler) + } + + @Test + fun startZramMaintenance() { + ZramMaintenance.startZramMaintenance(context) + + verify(mockJobScheduler, times(1)).schedule(jobInfoCaptor.capture()) + val job = jobInfoCaptor.value + assertThat(job.id).isEqualTo(ZramMaintenance.JOB_ID) + assertThat(job.extras.getBoolean(ZramMaintenance.KEY_CHECK_STATUS)).isTrue() + } + + @Test + fun startJobForFirstTime() { + val extras = PersistableBundle() + extras.putBoolean(ZramMaintenance.KEY_CHECK_STATUS, true) + val params = generateJobParameters( + ZramMaintenance.JOB_ID, + extras, + ) + `when`(mockMmd.isZramMaintenanceSupported()).thenReturn(true) + + ZramMaintenance.startJob(context, params, mockMmd) + + verify(mockMmd, times(1)).isZramMaintenanceSupported() + verify(mockMmd, times(1)).doZramMaintenanceAsync() + verify(mockJobScheduler, times(1)).schedule(jobInfoCaptor.capture()) + val nextJob = jobInfoCaptor.value + assertThat(nextJob.id).isEqualTo(ZramMaintenance.JOB_ID) + assertThat(nextJob.extras.getBoolean(ZramMaintenance.KEY_CHECK_STATUS)).isFalse() + } + + @Test + fun startJobWithoutCheckStatus() { + val extras = PersistableBundle() + extras.putBoolean(ZramMaintenance.KEY_CHECK_STATUS, false) + val params = generateJobParameters( + ZramMaintenance.JOB_ID, + extras, + ) + + ZramMaintenance.startJob(context, params, mockMmd) + + verify(mockMmd, never()).isZramMaintenanceSupported() + verify(mockMmd, times(1)).doZramMaintenanceAsync() + verify(mockJobScheduler, times(1)).schedule(jobInfoCaptor.capture()) + val nextJob = jobInfoCaptor.value + assertThat(nextJob.id).isEqualTo(ZramMaintenance.JOB_ID) + assertThat(nextJob.extras.getBoolean(ZramMaintenance.KEY_CHECK_STATUS)).isFalse() + } + + @Test + fun startJobZramIsDisabled() { + val extras = PersistableBundle() + extras.putBoolean(ZramMaintenance.KEY_CHECK_STATUS, true) + val params = generateJobParameters( + ZramMaintenance.JOB_ID, + extras, + ) + `when`(mockMmd.isZramMaintenanceSupported()).thenReturn(false) + + ZramMaintenance.startJob(context, params, mockMmd) + + verify(mockMmd, times(1)).isZramMaintenanceSupported() + verify(mockMmd, never()).doZramMaintenanceAsync() + verify(mockJobScheduler, never()).schedule(any()) + } + + @Test + fun startJobMmdIsNotReadyYet() { + val extras = PersistableBundle() + extras.putBoolean(ZramMaintenance.KEY_CHECK_STATUS, true) + val params = generateJobParameters( + ZramMaintenance.JOB_ID, + extras, + ) + + ZramMaintenance.startJob(context, params, null) + + verify(mockJobScheduler, times(1)).schedule(jobInfoCaptor.capture()) + val nextJob = jobInfoCaptor.value + assertThat(nextJob.id).isEqualTo(ZramMaintenance.JOB_ID) + assertThat(nextJob.extras.getBoolean(ZramMaintenance.KEY_CHECK_STATUS)).isTrue() + } +} \ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/zram/ZramMaintenanceTest.kt b/services/tests/servicestests/src/com/android/server/zram/ZramMaintenanceTest.kt deleted file mode 100644 index 5448a05aafc3..000000000000 --- a/services/tests/servicestests/src/com/android/server/zram/ZramMaintenanceTest.kt +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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.zram - -import android.app.job.JobInfo -import android.app.job.JobParameters -import android.app.job.JobScheduler -import android.os.IMmd -import android.os.PersistableBundle -import android.os.RemoteException -import android.testing.TestableContext -import androidx.test.filters.SmallTest -import androidx.test.platform.app.InstrumentationRegistry - -import com.android.server.ZramMaintenance -import com.google.common.truth.Truth.assertThat - -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import org.mockito.ArgumentCaptor -import org.mockito.Captor -import org.mockito.Mock -import org.mockito.Mockito.any -import org.mockito.Mockito.never -import org.mockito.Mockito.times -import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` -import org.mockito.MockitoAnnotations - -private fun generateJobParameters(jobId: Int, extras: PersistableBundle): JobParameters { - return JobParameters( - null, "", jobId, extras, null, null, 0, false, false, false, null, null, null - ) -} - -@SmallTest -@RunWith(JUnit4::class) -class ZramMaintenanceTest { - private val context = TestableContext(InstrumentationRegistry.getInstrumentation().context) - - @Captor - private lateinit var jobInfoCaptor: ArgumentCaptor - - @Mock - private lateinit var mockJobScheduler: JobScheduler - - @Mock - private lateinit var mockMmd: IMmd - - @Before - @Throws(RemoteException::class) - fun setUp() { - MockitoAnnotations.initMocks(this) - context.addMockSystemService(JobScheduler::class.java, mockJobScheduler) - } - - @Test - fun startZramMaintenance() { - ZramMaintenance.startZramMaintenance(context) - - verify(mockJobScheduler, times(1)).schedule(jobInfoCaptor.capture()) - val job = jobInfoCaptor.value - assertThat(job.id).isEqualTo(ZramMaintenance.JOB_ID) - assertThat(job.extras.getBoolean(ZramMaintenance.KEY_CHECK_STATUS)).isTrue() - } - - @Test - fun startJobForFirstTime() { - val extras = PersistableBundle() - extras.putBoolean(ZramMaintenance.KEY_CHECK_STATUS, true) - val params = generateJobParameters( - ZramMaintenance.JOB_ID, - extras, - ) - `when`(mockMmd.isZramMaintenanceSupported()).thenReturn(true) - - ZramMaintenance.startJob(context, params, mockMmd) - - verify(mockMmd, times(1)).isZramMaintenanceSupported() - verify(mockMmd, times(1)).doZramMaintenanceAsync() - verify(mockJobScheduler, times(1)).schedule(jobInfoCaptor.capture()) - val nextJob = jobInfoCaptor.value - assertThat(nextJob.id).isEqualTo(ZramMaintenance.JOB_ID) - assertThat(nextJob.extras.getBoolean(ZramMaintenance.KEY_CHECK_STATUS)).isFalse() - } - - @Test - fun startJobWithoutCheckStatus() { - val extras = PersistableBundle() - extras.putBoolean(ZramMaintenance.KEY_CHECK_STATUS, false) - val params = generateJobParameters( - ZramMaintenance.JOB_ID, - extras, - ) - - ZramMaintenance.startJob(context, params, mockMmd) - - verify(mockMmd, never()).isZramMaintenanceSupported() - verify(mockMmd, times(1)).doZramMaintenanceAsync() - verify(mockJobScheduler, times(1)).schedule(jobInfoCaptor.capture()) - val nextJob = jobInfoCaptor.value - assertThat(nextJob.id).isEqualTo(ZramMaintenance.JOB_ID) - assertThat(nextJob.extras.getBoolean(ZramMaintenance.KEY_CHECK_STATUS)).isFalse() - } - - @Test - fun startJobZramIsDisabled() { - val extras = PersistableBundle() - extras.putBoolean(ZramMaintenance.KEY_CHECK_STATUS, true) - val params = generateJobParameters( - ZramMaintenance.JOB_ID, - extras, - ) - `when`(mockMmd.isZramMaintenanceSupported()).thenReturn(false) - - ZramMaintenance.startJob(context, params, mockMmd) - - verify(mockMmd, times(1)).isZramMaintenanceSupported() - verify(mockMmd, never()).doZramMaintenanceAsync() - verify(mockJobScheduler, never()).schedule(any()) - } - - @Test - fun startJobMmdIsNotReadyYet() { - val extras = PersistableBundle() - extras.putBoolean(ZramMaintenance.KEY_CHECK_STATUS, true) - val params = generateJobParameters( - ZramMaintenance.JOB_ID, - extras, - ) - - ZramMaintenance.startJob(context, params, null) - - verify(mockJobScheduler, times(1)).schedule(jobInfoCaptor.capture()) - val nextJob = jobInfoCaptor.value - assertThat(nextJob.id).isEqualTo(ZramMaintenance.JOB_ID) - assertThat(nextJob.extras.getBoolean(ZramMaintenance.KEY_CHECK_STATUS)).isTrue() - } -} \ No newline at end of file -- cgit v1.2.3-59-g8ed1b