blob: 156c199cb466cb55fb4426fda5cc9201d8518542 [file] [log] [blame]
/*
* Copyright (C) 2019 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.alarmmanager.cts;
import static org.junit.Assert.fail;
import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
@AppModeFull
@RunWith(AndroidJUnit4.class)
public class UidCapTests {
private static final String TAG = UidCapTests.class.getSimpleName();
private static final String ACTION_PREFIX = "android.alarmmanager.cts.action.ALARM_";
private static final int SUFFICIENT_NUM_ALARMS = 450;
private static final int[] ALARM_TYPES = {
AlarmManager.RTC_WAKEUP,
AlarmManager.RTC,
AlarmManager.ELAPSED_REALTIME_WAKEUP,
AlarmManager.ELAPSED_REALTIME
};
private AlarmManager mAlarmManager;
private Context mContext;
private AlarmManagerDeviceConfigHelper mConfigHelper = new AlarmManagerDeviceConfigHelper();
private ArrayList<PendingIntent> mAlarmsSet = new ArrayList<>();
@Rule
public DumpLoggerRule mFailLoggerRule = new DumpLoggerRule(TAG);
@Before
public void setUp() {
mContext = InstrumentationRegistry.getTargetContext();
mAlarmManager = mContext.getSystemService(AlarmManager.class);
}
@Test
public void sufficientAlarmsAllowedByDefault() {
mConfigHelper.without("max_alarms_per_uid").commitAndAwaitPropagation();
for (int i = 1; i <= SUFFICIENT_NUM_ALARMS; i++) {
try {
final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
new Intent(ACTION_PREFIX + i), PendingIntent.FLAG_IMMUTABLE);
mAlarmManager.set(ALARM_TYPES[i % ALARM_TYPES.length], Long.MAX_VALUE, pi);
mAlarmsSet.add(pi);
} catch (Exception e) {
Log.e(TAG, "Could not set the " + i + "th alarm", e);
fail("Caught exception [" + e.getMessage() + "] while setting " + i + "th alarm");
}
}
}
@Test
public void alarmsCannotExceedLimit() {
final int limit = 598;
setMaxAlarmsPerUid(limit);
for (int i = 0; i < limit; i++) {
final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
new Intent(ACTION_PREFIX + i), PendingIntent.FLAG_IMMUTABLE);
mAlarmManager.set(ALARM_TYPES[i % ALARM_TYPES.length], Long.MAX_VALUE, pi);
mAlarmsSet.add(pi);
}
final PendingIntent lastPi = PendingIntent.getBroadcast(mContext, 0,
new Intent(ACTION_PREFIX + limit), PendingIntent.FLAG_IMMUTABLE);
for (int type : ALARM_TYPES) {
try {
mAlarmManager.set(type, Long.MAX_VALUE, lastPi);
mAlarmsSet.add(lastPi);
fail("Able to set an alarm of type " + type + " after reaching the limit of "
+ limit);
} catch (IllegalStateException e) {
}
}
}
private void setMaxAlarmsPerUid(int maxAlarmsPerUid) {
mConfigHelper.with("max_alarms_per_uid", maxAlarmsPerUid).commitAndAwaitPropagation();
}
@After
public void cancelAlarms() {
for (PendingIntent pi : mAlarmsSet) {
mAlarmManager.cancel(pi);
}
mAlarmsSet.clear();
}
@After
public void deleteAlarmManagerConstants() {
mConfigHelper.restoreAll();
}
}