Home | History | Annotate | Download | only in deviceowner
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.cts.deviceowner;
     17 
     18 import static android.provider.Settings.Global.AIRPLANE_MODE_ON;
     19 
     20 import static com.google.common.truth.Truth.assertThat;
     21 
     22 import android.app.admin.DevicePolicyManager;
     23 import android.app.admin.FreezePeriod;
     24 import android.app.admin.SystemUpdatePolicy;
     25 import android.app.admin.SystemUpdatePolicy.ValidationFailedException;
     26 import android.content.BroadcastReceiver;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.content.IntentFilter;
     30 import android.icu.util.Calendar;
     31 import android.os.Parcel;
     32 import android.provider.Settings;
     33 import android.provider.Settings.Global;
     34 import android.util.Log;
     35 import android.util.Pair;
     36 import android.provider.Settings;
     37 import android.provider.Settings.Global;
     38 
     39 import com.google.common.collect.ImmutableList;
     40 import java.time.LocalDate;
     41 import java.time.MonthDay;
     42 import java.util.ArrayList;
     43 import java.util.List;
     44 import java.util.Objects;
     45 import java.util.concurrent.CountDownLatch;
     46 import java.util.concurrent.Semaphore;
     47 import java.util.concurrent.TimeUnit;
     48 
     49 /**
     50  * Test {@link SystemUpdatePolicy}, {@link DevicePolicyManager#setSystemUpdatePolicy} and
     51  * {@link DevicePolicyManager#getSystemUpdatePolicy}
     52  */
     53 public class SystemUpdatePolicyTest extends BaseDeviceOwnerTest {
     54 
     55     private static final String TAG = "SystemUpdatePolicyTest";
     56 
     57     private static final int TIMEOUT_MS = 20_000;
     58     private static final int TIMEOUT_SEC = 5;
     59 
     60     private final Semaphore mPolicyChangedSemaphore = new Semaphore(0);
     61     private final Semaphore mTimeChangedSemaphore = new Semaphore(0);
     62     private final BroadcastReceiver policyChangedReceiver = new BroadcastReceiver() {
     63         @Override
     64         public void onReceive(Context context, Intent intent) {
     65             final String action = intent.getAction();
     66             if (DevicePolicyManager.ACTION_SYSTEM_UPDATE_POLICY_CHANGED.equals(action)) {
     67                 mPolicyChangedSemaphore.release();
     68             } else if (Intent.ACTION_TIME_CHANGED.equals(action)) {
     69                 mTimeChangedSemaphore.release();
     70             }
     71         }
     72     };
     73 
     74     private int mSavedAutoTimeConfig;
     75     private LocalDate mSavedSystemDate;
     76     private boolean mRestoreDate;
     77     private int mSavedAirplaneMode;
     78 
     79     @Override
     80     protected void setUp() throws Exception {
     81         super.setUp();
     82         IntentFilter filter = new IntentFilter();
     83         filter.addAction(DevicePolicyManager.ACTION_SYSTEM_UPDATE_POLICY_CHANGED);
     84         filter.addAction(Intent.ACTION_TIME_CHANGED);
     85         mContext.registerReceiver(policyChangedReceiver, filter);
     86         clearFreezeRecord();
     87         mSavedAutoTimeConfig = Settings.Global.getInt(mContext.getContentResolver(),
     88                 Global.AUTO_TIME, 0);
     89         executeShellCommand("settings put global auto_time 0");
     90         mSavedSystemDate = LocalDate.now();
     91         mRestoreDate = false;
     92         mSavedAirplaneMode = getAirplaneMode();
     93         Log.i(TAG, "Before testing, AIRPLANE_MODE is set to: " + mSavedAirplaneMode);
     94         if (mSavedAirplaneMode == 0) {
     95             // No need to set mode if AirplaneMode is 1 or error.
     96             setAirplaneModeAndWaitBroadcast(1);
     97         }
     98     }
     99 
    100     @Override
    101     protected void tearDown() throws Exception {
    102         mDevicePolicyManager.setSystemUpdatePolicy(getWho(), null);
    103         clearFreezeRecord();
    104         if (mRestoreDate) {
    105             setSystemDate(mSavedSystemDate);
    106         }
    107         executeShellCommand("settings put global auto_time",
    108                 Integer.toString(mSavedAutoTimeConfig));
    109         // This needs to happen last since setSystemDate() relies on the receiver for
    110         // synchronization.
    111         mContext.unregisterReceiver(policyChangedReceiver);
    112         if (mSavedAirplaneMode == 0) {
    113             // Restore AirplaneMode value.
    114             setAirplaneModeAndWaitBroadcast(0);
    115         }
    116         super.tearDown();
    117     }
    118 
    119     public void testSetEmptytInstallPolicy() {
    120         testPolicy(null);
    121     }
    122 
    123     public void testSetAutomaticInstallPolicy() {
    124         testPolicy(SystemUpdatePolicy.createAutomaticInstallPolicy());
    125     }
    126 
    127     public void testSetWindowedInstallPolicy() {
    128         testPolicy(SystemUpdatePolicy.createWindowedInstallPolicy(0, 720));
    129     }
    130 
    131     public void testSetPostponeInstallPolicy() {
    132         testPolicy(SystemUpdatePolicy.createPostponeInstallPolicy());
    133     }
    134 
    135     public void testShouldFailInvalidWindowPolicy() throws Exception {
    136         try {
    137             SystemUpdatePolicy.createWindowedInstallPolicy(24 * 60 + 1, 720);
    138             fail("Invalid window start should not be accepted.");
    139         } catch (IllegalArgumentException expected) { }
    140         try {
    141             SystemUpdatePolicy.createWindowedInstallPolicy(-1, 720);
    142             fail("Invalid window start should not be accepted.");
    143         } catch (IllegalArgumentException expected) { }
    144         try {
    145             SystemUpdatePolicy.createWindowedInstallPolicy(0, 24 * 60 + 1);
    146             fail("Invalid window end should not be accepted.");
    147         } catch (IllegalArgumentException expected) { }
    148         try {
    149             SystemUpdatePolicy.createWindowedInstallPolicy(0, -1);
    150             fail("Invalid window end should not be accepted.");
    151         } catch (IllegalArgumentException expected) { }
    152     }
    153 
    154     public void testFreezePeriodValidation() {
    155         // Dates are in MM-DD format
    156         validateFreezePeriodsSucceeds("01-01", "01-02");
    157         validateFreezePeriodsSucceeds("01-31", "01-31");
    158         validateFreezePeriodsSucceeds("11-01", "01-15");
    159         validateFreezePeriodsSucceeds("02-01", "02-29");
    160         validateFreezePeriodsSucceeds("03-01", "03-31", "09-01", "09-30");
    161         validateFreezePeriodsSucceeds("10-01", "10-31", "12-31", "01-31");
    162         validateFreezePeriodsSucceeds("01-01", "02-28", "05-01", "06-30", "09-01", "10-31");
    163         validateFreezePeriodsSucceeds("11-02", "01-15", "03-18", "04-30", "08-01", "08-30");
    164 
    165         // full overlap
    166         validateFreezePeriodsFailsOverlap("12-01", "01-31", "12-25", "01-15");
    167         // partial overlap
    168         validateFreezePeriodsFailsOverlap("03-01", "03-31", "03-15", "01-01");
    169         // touching interval
    170         validateFreezePeriodsFailsOverlap("01-31", "01-31", "02-01", "02-01");
    171         validateFreezePeriodsFailsOverlap("12-01", "12-31", "04-01", "04-01", "01-01", "01-30");
    172 
    173         // entire year
    174         validateFreezePeriodsFailsTooLong("01-01", "12-31");
    175         // Regular long period
    176         validateFreezePeriodsSucceeds("01-01", "03-31", "06-01", "08-29");
    177         validateFreezePeriodsFailsTooLong("01-01", "03-31", "06-01", "08-30");
    178         // long period spanning across year end
    179         validateFreezePeriodsSucceeds("11-01", "01-29");
    180         validateFreezePeriodsFailsTooLong("11-01", "01-30");
    181         // Leap year handling
    182         validateFreezePeriodsSucceeds("12-01", "02-28");
    183         validateFreezePeriodsFailsTooLong("12-01", "03-01");
    184 
    185         // Regular short separation
    186         validateFreezePeriodsFailsTooClose( "01-01", "01-01", "01-03", "01-03");
    187         // Short interval spans across end of year
    188         validateFreezePeriodsSucceeds("01-31", "03-01", "11-01", "12-01");
    189         validateFreezePeriodsFailsTooClose("01-30", "03-01", "11-01", "12-01");
    190         // Short separation is after wrapped period
    191         validateFreezePeriodsSucceeds("03-03", "03-31", "12-31", "01-01");
    192         validateFreezePeriodsFailsTooClose("03-02", "03-31", "12-31", "01-01");
    193         // Short separation including Feb 29
    194         validateFreezePeriodsSucceeds("12-01", "01-15", "03-17", "04-01");
    195         validateFreezePeriodsFailsTooClose("12-01", "01-15", "03-16", "04-01");
    196         // Short separation including Feb 29
    197         validateFreezePeriodsSucceeds("01-01", "02-28", "04-30", "06-01");
    198         validateFreezePeriodsSucceeds("01-01", "02-29", "04-30", "06-01");
    199         validateFreezePeriodsFailsTooClose("01-01", "03-01", "04-30", "06-01");
    200     }
    201 
    202     public void testFreezePeriodCanBeSetAndChanged() throws Exception {
    203         setPolicyWithFreezePeriod("11-02", "01-15", "03-18", "04-30");
    204         // Set to a different period should work
    205         setPolicyWithFreezePeriod("08-01", "08-30");
    206         // Clear freeze period should work
    207         setPolicyWithFreezePeriod();
    208         // Set to the original period should work
    209         setPolicyWithFreezePeriod("11-02", "01-15", "03-18", "04-30");
    210     }
    211 
    212     public void testFreezePeriodCannotSetIfTooCloseToPrevious() throws Exception {
    213         setSystemDate(LocalDate.of(2018, 2, 28));
    214         setPolicyWithFreezePeriod("01-01", "03-01", "06-01", "06-30");
    215         // Clear policy
    216         mDevicePolicyManager.setSystemUpdatePolicy(getWho(), null);
    217         // Set to a conflict period (too close with previous period [2-28, 2-28]) should fail,
    218         // despite the previous policy was cleared from the system just now.
    219         try {
    220             setPolicyWithFreezePeriod("04-29", "04-30");
    221             fail("Did no flag invalid period");
    222         } catch (ValidationFailedException e) {
    223             assertEquals(e.getMessage(),
    224                     ValidationFailedException.ERROR_COMBINED_FREEZE_PERIOD_TOO_CLOSE,
    225                     e.getErrorCode());
    226         }
    227         // This should succeed as the new freeze period is exactly 60 days away.
    228         setPolicyWithFreezePeriod("04-30", "04-30");
    229     }
    230 
    231     public void testFreezePeriodCannotSetIfTooLongWhenCombinedWithPrevious() throws Exception {
    232         setSystemDate(LocalDate.of(2012, 4, 1));
    233         setPolicyWithFreezePeriod("03-01", "05-01");
    234         setSystemDate(LocalDate.of(2012, 4, 30));
    235         // Despite the wait for broadcast in setSystemDate(), TIME_CHANGED broadcast is asynchronous
    236         // so give DevicePolicyManagerService more time to receive TIME_CHANGED and to update the
    237         // freeze period record.
    238         Thread.sleep(5000);
    239         // Set to a conflict period (too long when combined with previous period [04-01, 04-30])
    240         // should fail
    241         try {
    242             setPolicyWithFreezePeriod("04-30", "06-30");
    243             fail("Did no flag invalid period");
    244         } catch (SystemUpdatePolicy.ValidationFailedException e) {
    245             assertEquals(e.getMessage(),
    246                     ValidationFailedException.ERROR_COMBINED_FREEZE_PERIOD_TOO_LONG,
    247                     e.getErrorCode());
    248         }
    249         // This should succeed as the combined length (59 days) is just below threshold (90 days).
    250         setPolicyWithFreezePeriod("05-01", "06-29");
    251     }
    252 
    253     public void testFreezePeriodForOneYear() throws Exception {
    254         // Set a normal period every day for 365 days
    255         for (int i = 1; i <= 365; i++) {
    256             // Add two days so the test date range wraps around year-end
    257             setSystemDate(LocalDate.ofYearDay(2019, i).plusDays(2));
    258             testFreezePeriodCanBeSetAndChanged();
    259         }
    260     }
    261 
    262     public void testWriteSystemUpdatePolicyToParcel() {
    263         final Parcel parcel1 = Parcel.obtain();
    264         try {
    265             final SystemUpdatePolicy policy1 = SystemUpdatePolicy.createAutomaticInstallPolicy();
    266             policy1.writeToParcel(parcel1, 0);
    267             parcel1.setDataPosition(0);
    268             final SystemUpdatePolicy copy1 = SystemUpdatePolicy.CREATOR.createFromParcel(parcel1);
    269             assertThat(copy1).isNotNull();
    270             assertSystemUpdatePoliciesEqual(policy1, copy1);
    271         } finally {
    272             parcel1.recycle();
    273         }
    274 
    275         final Parcel parcel2 = Parcel.obtain();
    276         try {
    277             final SystemUpdatePolicy policy2 = SystemUpdatePolicy
    278                 .createWindowedInstallPolicy(0, 720);
    279             policy2.writeToParcel(parcel2, 0);
    280             parcel2.setDataPosition(0);
    281             final SystemUpdatePolicy copy2 = SystemUpdatePolicy.CREATOR.createFromParcel(parcel2);
    282             assertThat(copy2).isNotNull();
    283             assertSystemUpdatePoliciesEqual(policy2, copy2);
    284         } finally {
    285             parcel2.recycle();
    286         }
    287 
    288         final Parcel parcel3 = Parcel.obtain();
    289         try {
    290             final SystemUpdatePolicy policy3 = SystemUpdatePolicy.createPostponeInstallPolicy();
    291             policy3.writeToParcel(parcel3, 0);
    292             parcel3.setDataPosition(0);
    293             final SystemUpdatePolicy copy3 = SystemUpdatePolicy.CREATOR.createFromParcel(parcel3);
    294             assertThat(copy3).isNotNull();
    295             assertSystemUpdatePoliciesEqual(policy3, copy3);
    296         } finally {
    297             parcel3.recycle();
    298         }
    299     }
    300 
    301     public void testWriteValidationFailedExceptionToParcel() {
    302         final List<FreezePeriod> freezePeriods =
    303             ImmutableList.of(new FreezePeriod(MonthDay.of(1, 10), MonthDay.of(1, 9)));
    304         try {
    305             SystemUpdatePolicy.createAutomaticInstallPolicy().setFreezePeriods(freezePeriods);
    306             fail("ValidationFailedException not thrown for invalid freeze period.");
    307         } catch (ValidationFailedException e) {
    308             final Parcel parcel = Parcel.obtain();
    309             e.writeToParcel(parcel, 0);
    310             parcel.setDataPosition(0);
    311 
    312             final ValidationFailedException copy =
    313                 ValidationFailedException.CREATOR.createFromParcel(parcel);
    314 
    315             assertThat(copy).isNotNull();
    316             assertThat(e.getErrorCode()).isEqualTo(copy.getErrorCode());
    317             assertThat(e.getMessage()).isEqualTo(copy.getMessage());
    318         }
    319     }
    320 
    321     private void assertSystemUpdatePoliciesEqual(SystemUpdatePolicy policy,
    322             SystemUpdatePolicy copy) {
    323         assertThat(policy.getInstallWindowStart()).isEqualTo(copy.getInstallWindowStart());
    324         assertThat(policy.getInstallWindowEnd()).isEqualTo(copy.getInstallWindowEnd());
    325         assertFreezePeriodListsEqual(policy.getFreezePeriods(), copy.getFreezePeriods());
    326         assertThat(policy.getPolicyType()).isEqualTo(copy.getPolicyType());
    327     }
    328 
    329     private void assertFreezePeriodListsEqual(List<FreezePeriod> original,
    330             List<FreezePeriod> copy) {
    331         assertThat(original).isNotNull();
    332         assertThat(copy).isNotNull();
    333         assertThat(original.size()).isEqualTo(copy.size());
    334         for (FreezePeriod period1 : original) {
    335             assertThat(period1).isNotNull();
    336             assertFreezePeriodListContains(copy, period1);
    337         }
    338         for (FreezePeriod period1 : copy) {
    339             assertThat(period1).isNotNull();
    340             assertFreezePeriodListContains(original, period1);
    341         }
    342     }
    343 
    344     private void assertFreezePeriodListContains(List<FreezePeriod> list, FreezePeriod period) {
    345         for (FreezePeriod other : list) {
    346             assertThat(other).isNotNull();
    347             if (areFreezePeriodsEqual(period, other)) {
    348                 return;
    349             }
    350         }
    351         final List<String> printablePeriods = new ArrayList<>();
    352         for (FreezePeriod printablePeriod : list) {
    353             printablePeriods.add(printablePeriod.toString());
    354         }
    355         fail(String.format("FreezePeriod list [%s] does not contain the specified period %s.",
    356             String.join(", ", printablePeriods), period));
    357     }
    358 
    359     private boolean areFreezePeriodsEqual(FreezePeriod period1, FreezePeriod period2) {
    360         return period1 != null && period2 != null
    361             && Objects.equals(period1.getStart(), period2.getStart())
    362             && Objects.equals(period1.getEnd(), period2.getEnd());
    363     }
    364 
    365     private void testPolicy(SystemUpdatePolicy policy) {
    366         mDevicePolicyManager.setSystemUpdatePolicy(getWho(), policy);
    367         waitForPolicyChangedBroadcast();
    368         SystemUpdatePolicy newPolicy = mDevicePolicyManager.getSystemUpdatePolicy();
    369         if (policy == null) {
    370             assertNull(newPolicy);
    371         } else {
    372             assertNotNull(newPolicy);
    373             assertEquals(policy.toString(), newPolicy.toString());
    374             assertEquals(policy.getPolicyType(), newPolicy.getPolicyType());
    375             if (policy.getPolicyType() == SystemUpdatePolicy.TYPE_INSTALL_WINDOWED) {
    376                 assertEquals(policy.getInstallWindowStart(), newPolicy.getInstallWindowStart());
    377                 assertEquals(policy.getInstallWindowEnd(), newPolicy.getInstallWindowEnd());
    378             }
    379         }
    380     }
    381 
    382     private void setPolicyWithFreezePeriod(String...dates) {
    383         SystemUpdatePolicy policy = SystemUpdatePolicy.createPostponeInstallPolicy();
    384         setFreezePeriods(policy, dates);
    385         mDevicePolicyManager.setSystemUpdatePolicy(getWho(), policy);
    386 
    387         List<FreezePeriod> loadedFreezePeriods = mDevicePolicyManager
    388                 .getSystemUpdatePolicy().getFreezePeriods();
    389         assertEquals(dates.length / 2, loadedFreezePeriods.size());
    390         for (int i = 0; i < dates.length; i += 2) {
    391             assertEquals(parseMonthDay(dates[i]), loadedFreezePeriods.get(i / 2).getStart());
    392             assertEquals(parseMonthDay(dates[i + 1]), loadedFreezePeriods.get(i / 2).getEnd());
    393         }
    394     }
    395 
    396     private void validateFreezePeriodsSucceeds(String...dates)  {
    397         SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy();
    398         setFreezePeriods(p, dates);
    399     }
    400 
    401     private void validateFreezePeriodsFails(int errorCode, String... dates)  {
    402         SystemUpdatePolicy p = SystemUpdatePolicy.createPostponeInstallPolicy();
    403         try {
    404             setFreezePeriods(p, dates);
    405             fail("Exception not thrown for dates: " + String.join(" ", dates));
    406         } catch (SystemUpdatePolicy.ValidationFailedException e) {
    407             assertEquals("Exception not expected: " + e.getMessage(),
    408                     errorCode,e.getErrorCode());
    409         }
    410     }
    411 
    412     private void validateFreezePeriodsFailsOverlap(String... dates)  {
    413         validateFreezePeriodsFails(ValidationFailedException.ERROR_DUPLICATE_OR_OVERLAP, dates);
    414     }
    415 
    416     private void validateFreezePeriodsFailsTooLong(String... dates)  {
    417         validateFreezePeriodsFails(ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_LONG,
    418                 dates);
    419     }
    420 
    421     private void validateFreezePeriodsFailsTooClose(String... dates)  {
    422         validateFreezePeriodsFails(ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE,
    423                 dates);
    424     }
    425 
    426     //dates are in MM-DD format
    427     private void setFreezePeriods(SystemUpdatePolicy policy, String... dates) {
    428         List<FreezePeriod> periods = new ArrayList<>();
    429         for (int i = 0; i < dates.length; i+= 2) {
    430             periods.add(new FreezePeriod(parseMonthDay(dates[i]), parseMonthDay(dates[i + 1])));
    431         }
    432         policy.setFreezePeriods(periods);
    433     }
    434 
    435     private MonthDay parseMonthDay(String date) {
    436         return MonthDay.of(Integer.parseInt(date.substring(0, 2)),
    437                 Integer.parseInt(date.substring(3, 5)));
    438     }
    439 
    440     private void clearFreezeRecord() throws Exception {
    441         executeShellCommand("dpm", "clear-freeze-period-record");
    442     }
    443 
    444     private void setSystemDate(LocalDate date) throws Exception {
    445         mRestoreDate = true;
    446         Calendar c = Calendar.getInstance();
    447         c.set(Calendar.YEAR, date.getYear());
    448         c.set(Calendar.MONTH, date.getMonthValue() - 1);
    449         c.set(Calendar.DAY_OF_MONTH, date.getDayOfMonth());
    450         mDevicePolicyManager.setTime(getWho(), c.getTimeInMillis());
    451         waitForTimeChangedBroadcast();
    452     }
    453 
    454     private void waitForPolicyChangedBroadcast() {
    455         try {
    456             assertTrue("Timeout while waiting for broadcast.",
    457                     mPolicyChangedSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
    458         } catch (InterruptedException e) {
    459             fail("Interrupted while waiting for broadcast.");
    460         }
    461     }
    462 
    463     private void waitForTimeChangedBroadcast() {
    464         try {
    465             assertTrue("Timeout while waiting for broadcast.",
    466                     mTimeChangedSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
    467         } catch (InterruptedException e) {
    468             fail("Interrupted while waiting for broadcast.");
    469         }
    470     }
    471 
    472     private int getAirplaneMode() throws Settings.SettingNotFoundException {
    473         int airplaneMode = 0xFF;
    474         try {
    475             airplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
    476                 Settings.Global.AIRPLANE_MODE_ON);
    477         } catch (Settings.SettingNotFoundException e) {
    478             airplaneMode = 0xFF;
    479             // if the mode is not supported, return a non zero value.
    480             Log.i(TAG, "Airplane mode is not found in Settings. Skipping AirplaneMode update");
    481         } finally {
    482             return airplaneMode;
    483         }
    484     }
    485 
    486     private boolean setAirplaneModeAndWaitBroadcast (int state) throws Exception {
    487         Log.i(TAG, "setAirplaneModeAndWaitBroadcast setting state(0=disable, 1=enable): " + state);
    488 
    489         final CountDownLatch latch = new CountDownLatch(1);
    490         BroadcastReceiver receiver = new BroadcastReceiver() {
    491             @Override
    492             public void onReceive(Context context, Intent intent) {
    493                 Log.i(TAG, "Received broadcast for AirplaneModeUpdate");
    494                 latch.countDown();
    495             }
    496         };
    497         mContext.registerReceiver(receiver, new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
    498         try {
    499             Settings.Global.putInt(mContext.getContentResolver(), AIRPLANE_MODE_ON, state);
    500             if (!latch.await(TIMEOUT_SEC, TimeUnit.SECONDS)) {
    501                 Log.d(TAG, "Failed to receive broadcast in " + TIMEOUT_SEC + "sec");
    502                 return false;
    503             }
    504         } finally {
    505             mContext.unregisterReceiver(receiver);
    506         }
    507         return true;
    508     }
    509 }
    510