1 /*
2  * Copyright (C) 2018 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 
17 package android.perftests.utils;
18 
19 import static android.perftests.utils.SettingsHelper.NAMESPACE_SECURE;
20 
21 import android.content.ContentResolver;
22 import android.content.Context;
23 import android.database.ContentObserver;
24 import android.net.Uri;
25 import android.os.Handler;
26 import android.os.Looper;
27 import android.provider.Settings;
28 
29 import androidx.annotation.NonNull;
30 
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.TimeUnit;
33 
34 /**
35  * Helper used to block tests until a secure settings value has been updated.
36  */
37 public final class OneTimeSettingsListener extends ContentObserver {
38     private final CountDownLatch mLatch = new CountDownLatch(1);
39     private final ContentResolver mResolver;
40     private final String mKey;
41     private final int mTimeoutMs;
42 
OneTimeSettingsListener(@onNull Context context, @NonNull String namespace, @NonNull String key, int timeoutMs)43     public OneTimeSettingsListener(@NonNull Context context, @NonNull String namespace,
44             @NonNull String key, int timeoutMs) {
45         super(new Handler(Looper.getMainLooper()));
46         mKey = key;
47         mResolver = context.getContentResolver();
48         mTimeoutMs = timeoutMs;
49         final Uri uri;
50         switch (namespace) {
51             case NAMESPACE_SECURE:
52                 uri = Settings.Secure.getUriFor(key);
53                 break;
54             default:
55                 throw new IllegalArgumentException("invalid namespace: " + namespace);
56         }
57         mResolver.registerContentObserver(uri, false, this);
58     }
59 
60     @Override
onChange(boolean selfChange, Uri uri)61     public void onChange(boolean selfChange, Uri uri) {
62         mResolver.unregisterContentObserver(this);
63         mLatch.countDown();
64     }
65 
66     /**
67      * Blocks for a few seconds until it's called, or throws an {@link IllegalStateException} if
68      * it isn't.
69      */
assertCalled()70     public void assertCalled() {
71         try {
72             final boolean updated = mLatch.await(mTimeoutMs, TimeUnit.MILLISECONDS);
73             if (!updated) {
74                 throw new IllegalStateException(
75                         "Settings " + mKey + " not called in " + mTimeoutMs + "ms");
76             }
77         } catch (InterruptedException e) {
78             Thread.currentThread().interrupt();
79             throw new IllegalStateException("Interrupted", e);
80         }
81     }
82 }
83