text: /*
   * Copyright (C) 2017 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 static android.app.AlarmManager.RTC;
  import static android.app.AlarmManager.RTC_WAKEUP;
  
  import static org.junit.Assert.assertEquals;
  
  import android.util.SparseArray;
  
  import androidx.test.filters.SmallTest;
  import androidx.test.runner.AndroidJUnit4;
  
  import com.android.internal.util.ObjectUtils;
  import com.android.server.AlarmManagerService.Alarm;
  
  import org.junit.Test;
  import org.junit.runner.RunWith;
  
  import java.util.ArrayList;
  
  @SmallTest
  @RunWith(AndroidJUnit4.class)
  public class BackgroundRestrictedAlarmsTest {
      private SparseArray<ArrayList<Alarm>> addPendingAlarm(
              SparseArray<ArrayList<Alarm>> all, int uid, String name, boolean removeIt) {
          ArrayList<Alarm> uidAlarms = all.get(uid);
          if (uidAlarms == null) {
              all.put(uid, uidAlarms = new ArrayList<>());
          }
          uidAlarms.add(new Alarm(
                  removeIt ? RTC : RTC_WAKEUP,
                  0, 0, 0, 0, 0, null, null, null, null, 0, null, uid, name));
          return all;
      }
  
      private static String toString(SparseArray<ArrayList<Alarm>> pendingAlarms) {
          final StringBuilder sb = new StringBuilder();
  
          String sep = "";
          for (int i = 0; i < pendingAlarms.size(); i++) {
              sb.append(sep);
              sep = ", ";
              sb.append("[");
              sb.append(pendingAlarms.keyAt(i));
              sb.append(": ");
              sb.append(toString(pendingAlarms.valueAt(i)));
              sb.append("]");
          }
          return sb.toString();
      }
  
      private static String toString(ArrayList<Alarm> alarms) {
          final StringBuilder sb = new StringBuilder();
  
          alarms.sort((a, b) -> ObjectUtils.compare(a.packageName, b.packageName));
  
          String sep = "";
          for (Alarm a : alarms) {
              sb.append(sep);
              sep = ", ";
              sb.append(a.packageName);
          }
          return sb.toString();
      }
  
      private void runCheckAllPendingAlarms(
              SparseArray<ArrayList<Alarm>> pending, ArrayList<Alarm> alarmsToDeliver) {
          // RTC_WAKEUP alarms are restricted.
          AlarmManagerService.findAllUnrestrictedPendingBackgroundAlarmsLockedInner(pending,
                  alarmsToDeliver, alarm -> alarm.type == RTC_WAKEUP);
      }
  
      @Test
      public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_empty() {
          SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
  
          final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
  
          runCheckAllPendingAlarms(pending, alarmsToDeliver);
  
          assertEquals("", toString(pending));
          assertEquals("", toString(alarmsToDeliver));
      }
  
      @Test
      public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_single_remove() {
          SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
  
          addPendingAlarm(pending, 100001, "a1", false);
  
          final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
  
          runCheckAllPendingAlarms(pending, alarmsToDeliver);
  
          assertEquals("[100001: a1]", toString(pending));
          assertEquals("", toString(alarmsToDeliver));
      }
  
      @Test
      public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_single_nonremove() {
          SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
  
          addPendingAlarm(pending, 100001, "a1", true);
  
          final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
          runCheckAllPendingAlarms(pending, alarmsToDeliver);
  
  
          assertEquals("", toString(pending));
          assertEquals("a1", toString(alarmsToDeliver));
      }
  
      @Test
      public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_complex() {
          SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
  
          addPendingAlarm(pending, 100001, "a11", false);
          addPendingAlarm(pending, 100001, "a12", true);
          addPendingAlarm(pending, 100001, "a13", false);
          addPendingAlarm(pending, 100001, "a14", true);
  
          addPendingAlarm(pending, 100002, "a21", false);
  
          addPendingAlarm(pending, 100003, "a31", true);
  
          addPendingAlarm(pending, 100004, "a41", false);
          addPendingAlarm(pending, 100004, "a42", false);
  
          addPendingAlarm(pending, 100005, "a51", true);
          addPendingAlarm(pending, 100005, "a52", true);
  
          addPendingAlarm(pending, 100006, "a61", true);
          addPendingAlarm(pending, 100006, "a62", false);
          addPendingAlarm(pending, 100006, "a63", true);
          addPendingAlarm(pending, 100006, "a64", false);
  
          final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
          runCheckAllPendingAlarms(pending, alarmsToDeliver);
  
  
          assertEquals("[100001: a11, a13], [100002: a21], [100004: a41, a42], [100006: a62, a64]",
                  toString(pending));
          assertEquals("a12, a14, a31, a51, a52, a61, a63", toString(alarmsToDeliver));
      }
  
      @Test
      public void findAllUnrestrictedPendingBackgroundAlarmsLockedInner_complex_allRemove() {
          SparseArray<ArrayList<Alarm>> pending = new SparseArray<>();
  
          addPendingAlarm(pending, 100001, "a11", true);
          addPendingAlarm(pending, 100001, "a12", true);
          addPendingAlarm(pending, 100001, "a13", true);
          addPendingAlarm(pending, 100001, "a14", true);
  
          addPendingAlarm(pending, 100002, "a21", true);
  
          addPendingAlarm(pending, 100003, "a31", true);
  
          addPendingAlarm(pending, 100004, "a41", true);
          addPendingAlarm(pending, 100004, "a42", true);
  
          addPendingAlarm(pending, 100005, "a51", true);
          addPendingAlarm(pending, 100005, "a52", true);
  
          addPendingAlarm(pending, 100006, "a61", true);
          addPendingAlarm(pending, 100006, "a62", true);
          addPendingAlarm(pending, 100006, "a63", true);
          addPendingAlarm(pending, 100006, "a64", true);
  
          final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
          runCheckAllPendingAlarms(pending, alarmsToDeliver);
  
  
          assertEquals("", toString(pending));
          assertEquals("a11, a12, a13, a14, a21, a31, a41, a42, a51, a52, a61, a62, a63, a64",
                  toString(alarmsToDeliver));
      }
  }
  