Merge "[HWUI] use native_window timestamp apis"
diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp
new file mode 100644
index 0000000..be5072c
--- /dev/null
+++ b/apct-tests/perftests/blobstore/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 2020 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.
+
+android_test {
+ name: "BlobStorePerfTests",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "BlobStoreTestUtils",
+ "androidx.test.rules",
+ "androidx.annotation_annotation",
+ "apct-perftests-utils",
+ "ub-uiautomator",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ certificate: "platform",
+}
\ No newline at end of file
diff --git a/apct-tests/perftests/blobstore/AndroidManifest.xml b/apct-tests/perftests/blobstore/AndroidManifest.xml
new file mode 100644
index 0000000..21d0726
--- /dev/null
+++ b/apct-tests/perftests/blobstore/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.perftests.blob">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.perftests.blob"/>
+
+</manifest>
\ No newline at end of file
diff --git a/apct-tests/perftests/blobstore/AndroidTest.xml b/apct-tests/perftests/blobstore/AndroidTest.xml
new file mode 100644
index 0000000..19456c6
--- /dev/null
+++ b/apct-tests/perftests/blobstore/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Runs BlobStorePerfTests metric instrumentation.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-metric-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="BlobStorePerfTests.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.perftests.blob" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java
new file mode 100644
index 0000000..0208dab
--- /dev/null
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2020 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.perftests.blob;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.os.ParcelFileDescriptor;
+import android.perftests.utils.TraceMarkParser;
+import android.perftests.utils.TraceMarkParser.TraceMarkSlice;
+import android.support.test.uiautomator.UiDevice;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.function.BiConsumer;
+
+// Copy of com.android.frameworks.perftests.am.util.AtraceUtils. TODO: avoid this duplication.
+public class AtraceUtils {
+ private static final String TAG = "AtraceUtils";
+ private static final boolean VERBOSE = true;
+
+ private static final String ATRACE_START = "atrace --async_start -b %d -c %s";
+ private static final String ATRACE_DUMP = "atrace --async_dump";
+ private static final String ATRACE_STOP = "atrace --async_stop";
+ private static final int DEFAULT_ATRACE_BUF_SIZE = 1024;
+
+ private UiAutomation mAutomation;
+ private static AtraceUtils sUtils = null;
+ private boolean mStarted = false;
+
+ private AtraceUtils(Instrumentation instrumentation) {
+ mAutomation = instrumentation.getUiAutomation();
+ }
+
+ public static AtraceUtils getInstance(Instrumentation instrumentation) {
+ if (sUtils == null) {
+ sUtils = new AtraceUtils(instrumentation);
+ }
+ return sUtils;
+ }
+
+ /**
+ * @param categories The list of the categories to trace, separated with space.
+ */
+ public void startTrace(String categories) {
+ synchronized (this) {
+ if (mStarted) {
+ throw new IllegalStateException("atrace already started");
+ }
+ runShellCommand(String.format(
+ ATRACE_START, DEFAULT_ATRACE_BUF_SIZE, categories));
+ mStarted = true;
+ }
+ }
+
+ public void stopTrace() {
+ synchronized (this) {
+ mStarted = false;
+ runShellCommand(ATRACE_STOP);
+ }
+ }
+
+ private String runShellCommand(String cmd) {
+ try {
+ return UiDevice.getInstance(
+ InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * @param parser The function that can accept the buffer of atrace dump and parse it.
+ * @param handler The parse result handler
+ */
+ public void performDump(TraceMarkParser parser,
+ BiConsumer<String, List<TraceMarkSlice>> handler) {
+ parser.reset();
+ try {
+ if (VERBOSE) {
+ Log.i(TAG, "Collecting atrace dump...");
+ }
+ writeDataToBuf(mAutomation.executeShellCommand(ATRACE_DUMP), parser);
+ } catch (IOException e) {
+ Log.e(TAG, "Error in reading dump", e);
+ }
+ parser.forAllSlices(handler);
+ }
+
+ // The given file descriptor here will be closed by this function
+ private void writeDataToBuf(ParcelFileDescriptor pfDescriptor,
+ TraceMarkParser parser) throws IOException {
+ InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfDescriptor);
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ parser.visit(line);
+ }
+ }
+ }
+}
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
new file mode 100644
index 0000000..a7b69c4
--- /dev/null
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2020 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.perftests.blob;
+
+import android.app.blob.BlobStoreManager;
+import android.content.Context;
+import android.perftests.utils.ManualBenchmarkState;
+import android.perftests.utils.PerfManualStatusReporter;
+import android.perftests.utils.TraceMarkParser;
+import android.perftests.utils.TraceMarkParser.TraceMarkSlice;
+import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.utils.blob.DummyBlobData;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@LargeTest
+@RunWith(Parameterized.class)
+public class BlobStorePerfTests {
+ // From frameworks/native/cmds/atrace/atrace.cpp
+ private static final String ATRACE_CATEGORY_SYSTEM_SERVER = "ss";
+ // From f/b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+ private static final String ATRACE_COMPUTE_DIGEST_PREFIX = "computeBlobDigest-";
+
+ private Context mContext;
+ private BlobStoreManager mBlobStoreManager;
+ private AtraceUtils mAtraceUtils;
+ private ManualBenchmarkState mState;
+
+ @Rule
+ public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
+
+ @Parameterized.Parameter(0)
+ public int fileSizeInMb;
+
+ @Parameterized.Parameters(name = "{0}MB")
+ public static Collection<Object[]> getParameters() {
+ return Arrays.asList(new Object[][] {
+ { 25 },
+ { 50 },
+ { 100 },
+ { 200 },
+ });
+ }
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mBlobStoreManager = (BlobStoreManager) mContext.getSystemService(
+ Context.BLOB_STORE_SERVICE);
+ mAtraceUtils = AtraceUtils.getInstance(InstrumentationRegistry.getInstrumentation());
+ mState = mPerfManualStatusReporter.getBenchmarkState();
+ }
+
+ @After
+ public void tearDown() {
+ // TODO: Add a blob_store shell command to trigger idle maintenance to avoid hardcoding
+ // job id like this.
+ // From BlobStoreConfig.IDLE_JOB_ID = 191934935.
+ runShellCommand("cmd jobscheduler run -f android 191934935");
+ }
+
+ @Test
+ public void testComputeDigest() throws Exception {
+ mAtraceUtils.startTrace(ATRACE_CATEGORY_SYSTEM_SERVER);
+ try {
+ final List<Long> durations = new ArrayList<>();
+ final DummyBlobData blobData = prepareDataBlob(fileSizeInMb);
+ final TraceMarkParser parser = new TraceMarkParser(
+ line -> line.name.startsWith(ATRACE_COMPUTE_DIGEST_PREFIX));
+ while (mState.keepRunning(durations)) {
+ commitBlob(blobData);
+
+ durations.clear();
+ collectDigestDurationsFromTrace(parser, durations);
+ // get and delete blobId
+ }
+ } finally {
+ mAtraceUtils.stopTrace();
+ }
+ }
+
+ private void collectDigestDurationsFromTrace(TraceMarkParser parser, List<Long> durations) {
+ mAtraceUtils.performDump(parser, (key, slices) -> {
+ for (TraceMarkSlice slice : slices) {
+ durations.add(TimeUnit.MICROSECONDS.toNanos(slice.getDurationInMicroseconds()));
+ }
+ });
+ }
+
+ private DummyBlobData prepareDataBlob(int fileSizeInMb) throws Exception {
+ final DummyBlobData blobData = new DummyBlobData(mContext,
+ fileSizeInMb * 1024 * 1024 /* bytes */);
+ blobData.prepare();
+ return blobData;
+ }
+
+ private void commitBlob(DummyBlobData blobData) throws Exception {
+ final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
+ try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
+ blobData.writeToSession(session);
+ final CompletableFuture<Integer> callback = new CompletableFuture<>();
+ session.commit(mContext.getMainExecutor(), callback::complete);
+ // Ignore commit callback result.
+ callback.get();
+ }
+ }
+
+ private String runShellCommand(String cmd) {
+ try {
+ return UiDevice.getInstance(
+ InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/apex/blobstore/TEST_MAPPING b/apex/blobstore/TEST_MAPPING
index cfe19a5..25a1537 100644
--- a/apex/blobstore/TEST_MAPPING
+++ b/apex/blobstore/TEST_MAPPING
@@ -4,7 +4,7 @@
"name": "CtsBlobStoreTestCases"
},
{
- "name": "FrameworksServicesTests",
+ "name": "FrameworksMockingServicesTests",
"options": [
{
"include-filter": "com.android.server.blob"
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobHandle.java b/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
index f110b36..d339afa 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
@@ -257,6 +257,11 @@
return Base64.encodeToString(digest, Base64.NO_WRAP);
}
+ /** @hide */
+ public boolean isExpired() {
+ return expiryTimeMillis != 0 && expiryTimeMillis < System.currentTimeMillis();
+ }
+
public static final @NonNull Creator<BlobHandle> CREATOR = new Creator<BlobHandle>() {
@Override
public @NonNull BlobHandle createFromParcel(@NonNull Parcel source) {
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index aba3e8c..c12e0ec 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -64,9 +64,9 @@
private final Context mContext;
- public final long blobId;
- public final BlobHandle blobHandle;
- public final int userId;
+ private final long mBlobId;
+ private final BlobHandle mBlobHandle;
+ private final int mUserId;
@GuardedBy("mMetadataLock")
private final ArraySet<Committer> mCommitters = new ArraySet<>();
@@ -90,9 +90,21 @@
BlobMetadata(Context context, long blobId, BlobHandle blobHandle, int userId) {
mContext = context;
- this.blobId = blobId;
- this.blobHandle = blobHandle;
- this.userId = userId;
+ this.mBlobId = blobId;
+ this.mBlobHandle = blobHandle;
+ this.mUserId = userId;
+ }
+
+ long getBlobId() {
+ return mBlobId;
+ }
+
+ BlobHandle getBlobHandle() {
+ return mBlobHandle;
+ }
+
+ int getUserId() {
+ return mUserId;
}
void addCommitter(@NonNull Committer committer) {
@@ -159,7 +171,7 @@
boolean hasLeases() {
synchronized (mMetadataLock) {
- return mLeasees.isEmpty();
+ return !mLeasees.isEmpty();
}
}
@@ -196,7 +208,7 @@
File getBlobFile() {
if (mBlobFile == null) {
- mBlobFile = BlobStoreConfig.getBlobFile(blobId);
+ mBlobFile = BlobStoreConfig.getBlobFile(mBlobId);
}
return mBlobFile;
}
@@ -244,7 +256,7 @@
void dump(IndentingPrintWriter fout, DumpArgs dumpArgs) {
fout.println("blobHandle:");
fout.increaseIndent();
- blobHandle.dump(fout, dumpArgs.shouldDumpFull());
+ mBlobHandle.dump(fout, dumpArgs.shouldDumpFull());
fout.decreaseIndent();
fout.println("Committers:");
@@ -274,11 +286,11 @@
void writeToXml(XmlSerializer out) throws IOException {
synchronized (mMetadataLock) {
- XmlUtils.writeLongAttribute(out, ATTR_ID, blobId);
- XmlUtils.writeIntAttribute(out, ATTR_USER_ID, userId);
+ XmlUtils.writeLongAttribute(out, ATTR_ID, mBlobId);
+ XmlUtils.writeIntAttribute(out, ATTR_USER_ID, mUserId);
out.startTag(null, TAG_BLOB_HANDLE);
- blobHandle.writeToXml(out);
+ mBlobHandle.writeToXml(out);
out.endTag(null, TAG_BLOB_HANDLE);
for (int i = 0, count = mCommitters.size(); i < count; ++i) {
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
index eb414b0..ba2e559 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
@@ -18,12 +18,15 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Environment;
+import android.util.Log;
import android.util.Slog;
import java.io.File;
+import java.util.concurrent.TimeUnit;
class BlobStoreConfig {
public static final String TAG = "BlobStore";
+ public static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
public static final int CURRENT_XML_VERSION = 1;
@@ -32,6 +35,20 @@
private static final String SESSIONS_INDEX_FILE_NAME = "sessions_index.xml";
private static final String BLOBS_INDEX_FILE_NAME = "blobs_index.xml";
+ /**
+ * Job Id for idle maintenance job ({@link BlobStoreIdleJobService}).
+ */
+ public static final int IDLE_JOB_ID = 0xB70B1D7; // 191934935L
+ /**
+ * Max time period (in millis) between each idle maintenance job run.
+ */
+ public static final long IDLE_JOB_PERIOD_MILLIS = TimeUnit.DAYS.toMillis(1);
+
+ /**
+ * Timeout in millis after which sessions with no updates will be deleted.
+ */
+ public static final long SESSION_EXPIRY_TIMEOUT_MILLIS = TimeUnit.DAYS.toMillis(7);
+
@Nullable
public static File prepareBlobFile(long sessionId) {
final File blobsDir = prepareBlobsDir();
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreIdleJobService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreIdleJobService.java
new file mode 100644
index 0000000..460e776
--- /dev/null
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreIdleJobService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 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.blob;
+
+import static com.android.server.blob.BlobStoreConfig.IDLE_JOB_ID;
+import static com.android.server.blob.BlobStoreConfig.IDLE_JOB_PERIOD_MILLIS;
+import static com.android.server.blob.BlobStoreConfig.LOGV;
+import static com.android.server.blob.BlobStoreConfig.TAG;
+
+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.AsyncTask;
+import android.util.Slog;
+
+import com.android.server.LocalServices;
+
+/**
+ * Maintenance job to clean up stale sessions and blobs.
+ */
+public class BlobStoreIdleJobService extends JobService {
+ @Override
+ public boolean onStartJob(final JobParameters params) {
+ AsyncTask.execute(() -> {
+ final BlobStoreManagerInternal blobStoreManagerInternal = LocalServices.getService(
+ BlobStoreManagerInternal.class);
+ blobStoreManagerInternal.onIdleMaintenance();
+ jobFinished(params, false);
+ });
+ return false;
+ }
+
+ @Override
+ public boolean onStopJob(final JobParameters params) {
+ Slog.d(TAG, "Idle maintenance job is stopped; id=" + params.getJobId()
+ + ", reason=" + JobParameters.getReasonCodeDescription(params.getStopReason()));
+ return false;
+ }
+
+ static void schedule(Context context) {
+ final JobScheduler jobScheduler = (JobScheduler) context.getSystemService(
+ Context.JOB_SCHEDULER_SERVICE);
+ final JobInfo job = new JobInfo.Builder(IDLE_JOB_ID,
+ new ComponentName(context, BlobStoreIdleJobService.class))
+ .setRequiresDeviceIdle(true)
+ .setRequiresCharging(true)
+ .setPeriodic(IDLE_JOB_PERIOD_MILLIS)
+ .build();
+ jobScheduler.schedule(job);
+ if (LOGV) {
+ Slog.v(TAG, "Scheduling the idle maintenance job");
+ }
+ }
+}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerInternal.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerInternal.java
new file mode 100644
index 0000000..5358245
--- /dev/null
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerInternal.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020 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.blob;
+
+/**
+ * BlobStoreManager local system service interface.
+ *
+ * Only for use within the system server.
+ */
+public abstract class BlobStoreManagerInternal {
+ /**
+ * Triggered from idle maintenance job to cleanup stale blobs and sessions.
+ */
+ public abstract void onIdleMaintenance();
+}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 13f095e..0ba34ca 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -28,6 +28,8 @@
import static android.os.UserHandle.USER_NULL;
import static com.android.server.blob.BlobStoreConfig.CURRENT_XML_VERSION;
+import static com.android.server.blob.BlobStoreConfig.LOGV;
+import static com.android.server.blob.BlobStoreConfig.SESSION_EXPIRY_TIMEOUT_MILLIS;
import static com.android.server.blob.BlobStoreConfig.TAG;
import static com.android.server.blob.BlobStoreSession.STATE_ABANDONED;
import static com.android.server.blob.BlobStoreSession.STATE_COMMITTED;
@@ -61,6 +63,7 @@
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.ExceptionUtils;
import android.util.LongSparseArray;
@@ -94,8 +97,10 @@
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* Service responsible for maintaining and facilitating access to data blobs published by apps.
@@ -115,6 +120,10 @@
@GuardedBy("mBlobsLock")
private final SparseArray<ArrayMap<BlobHandle, BlobMetadata>> mBlobsMap = new SparseArray<>();
+ // Contains all ids that are currently in use.
+ @GuardedBy("mBlobsLock")
+ private final ArraySet<Long> mKnownBlobIds = new ArraySet<>();
+
private final Context mContext;
private final Handler mHandler;
private final Injector mInjector;
@@ -151,6 +160,7 @@
@Override
public void onStart() {
publishBinderService(Context.BLOB_STORE_SERVICE, new Stub());
+ LocalServices.addService(BlobStoreManagerInternal.class, new LocalService());
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
registerReceivers();
@@ -164,6 +174,8 @@
readBlobSessionsLocked(allPackages);
readBlobsInfoLocked(allPackages);
}
+ } else if (phase == PHASE_BOOT_COMPLETED) {
+ BlobStoreIdleJobService.schedule(mContext);
}
}
@@ -215,6 +227,40 @@
}
}
+ @VisibleForTesting
+ void addKnownIdsForTest(long... knownIds) {
+ synchronized (mBlobsLock) {
+ for (long id : knownIds) {
+ mKnownBlobIds.add(id);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ Set<Long> getKnownIdsForTest() {
+ synchronized (mBlobsLock) {
+ return mKnownBlobIds;
+ }
+ }
+
+ @GuardedBy("mBlobsLock")
+ private void addSessionForUserLocked(BlobStoreSession session, int userId) {
+ getUserSessionsLocked(userId).put(session.getSessionId(), session);
+ mKnownBlobIds.add(session.getSessionId());
+ }
+
+ @GuardedBy("mBlobsLock")
+ private void addBlobForUserLocked(BlobMetadata blobMetadata, int userId) {
+ addBlobForUserLocked(blobMetadata, getUserBlobsLocked(userId));
+ }
+
+ @GuardedBy("mBlobsLock")
+ private void addBlobForUserLocked(BlobMetadata blobMetadata,
+ ArrayMap<BlobHandle, BlobMetadata> userBlobs) {
+ userBlobs.put(blobMetadata.getBlobHandle(), blobMetadata);
+ mKnownBlobIds.add(blobMetadata.getBlobId());
+ }
+
private long createSessionInternal(BlobHandle blobHandle,
int callingUid, String callingPackage) {
synchronized (mBlobsLock) {
@@ -223,7 +269,11 @@
final BlobStoreSession session = new BlobStoreSession(mContext,
sessionId, blobHandle, callingUid, callingPackage,
mSessionStateChangeListener);
- getUserSessionsLocked(UserHandle.getUserId(callingUid)).put(sessionId, session);
+ addSessionForUserLocked(session, UserHandle.getUserId(callingUid));
+ if (LOGV) {
+ Slog.v(TAG, "Created session for " + blobHandle
+ + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
+ }
writeBlobSessionsAsync();
return sessionId;
}
@@ -251,7 +301,10 @@
callingUid, callingPackage);
session.open();
session.abandon();
-
+ if (LOGV) {
+ Slog.v(TAG, "Deleted session with id " + sessionId
+ + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
+ }
writeBlobSessionsAsync();
}
}
@@ -286,6 +339,10 @@
}
blobMetadata.addLeasee(callingPackage, callingUid,
descriptionResId, leaseExpiryTimeMillis);
+ if (LOGV) {
+ Slog.v(TAG, "Acquired lease on " + blobHandle
+ + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
+ }
writeBlobsInfoAsync();
}
}
@@ -301,6 +358,10 @@
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
}
blobMetadata.removeLeasee(callingPackage, callingUid);
+ if (LOGV) {
+ Slog.v(TAG, "Released lease on " + blobHandle
+ + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
+ }
writeBlobsInfoAsync();
}
}
@@ -329,6 +390,10 @@
session.getSessionFile().delete();
getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid()))
.remove(session.getSessionId());
+ mKnownBlobIds.remove(session.getSessionId());
+ if (LOGV) {
+ Slog.v(TAG, "Session is invalid; deleted " + session);
+ }
break;
case STATE_COMMITTED:
session.verifyBlobData();
@@ -340,7 +405,7 @@
if (blob == null) {
blob = new BlobMetadata(mContext,
session.getSessionId(), session.getBlobHandle(), userId);
- userBlobs.put(session.getBlobHandle(), blob);
+ addBlobForUserLocked(blob, userBlobs);
}
final Committer newCommitter = new Committer(session.getOwnerPackageName(),
session.getOwnerUid(), session.getBlobAccessMode());
@@ -355,6 +420,9 @@
}
getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid()))
.remove(session.getSessionId());
+ if (LOGV) {
+ Slog.v(TAG, "Successfully committed session " + session);
+ }
break;
default:
Slog.wtf(TAG, "Invalid session state: "
@@ -397,6 +465,9 @@
out.endTag(null, TAG_SESSIONS);
out.endDocument();
sessionsIndexFile.finishWrite(fos);
+ if (LOGV) {
+ Slog.v(TAG, "Finished persisting sessions data");
+ }
} catch (Exception e) {
sessionsIndexFile.failWrite(fos);
Slog.wtf(TAG, "Error writing sessions data", e);
@@ -437,8 +508,8 @@
if (userPackages != null
&& session.getOwnerPackageName().equals(
userPackages.get(session.getOwnerUid()))) {
- getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid())).put(
- session.getSessionId(), session);
+ addSessionForUserLocked(session,
+ UserHandle.getUserId(session.getOwnerUid()));
} else {
// Unknown package or the session data does not belong to this package.
session.getSessionFile().delete();
@@ -446,6 +517,9 @@
mCurrentMaxSessionId = Math.max(mCurrentMaxSessionId, session.getSessionId());
}
}
+ if (LOGV) {
+ Slog.v(TAG, "Finished reading sessions data");
+ }
} catch (Exception e) {
Slog.wtf(TAG, "Error reading sessions data", e);
}
@@ -479,6 +553,9 @@
out.endTag(null, TAG_BLOBS);
out.endDocument();
blobsIndexFile.finishWrite(fos);
+ if (LOGV) {
+ Slog.v(TAG, "Finished persisting blobs data");
+ }
} catch (Exception e) {
blobsIndexFile.failWrite(fos);
Slog.wtf(TAG, "Error writing blobs data", e);
@@ -510,18 +587,21 @@
if (TAG_BLOB.equals(in.getName())) {
final BlobMetadata blobMetadata = BlobMetadata.createFromXml(mContext, in);
- final SparseArray<String> userPackages = allPackages.get(blobMetadata.userId);
+ final SparseArray<String> userPackages = allPackages.get(
+ blobMetadata.getUserId());
if (userPackages == null) {
blobMetadata.getBlobFile().delete();
} else {
- getUserBlobsLocked(blobMetadata.userId).put(
- blobMetadata.blobHandle, blobMetadata);
+ addBlobForUserLocked(blobMetadata, blobMetadata.getUserId());
blobMetadata.removeInvalidCommitters(userPackages);
blobMetadata.removeInvalidLeasees(userPackages);
}
- mCurrentMaxSessionId = Math.max(mCurrentMaxSessionId, blobMetadata.blobId);
+ mCurrentMaxSessionId = Math.max(mCurrentMaxSessionId, blobMetadata.getBlobId());
}
}
+ if (LOGV) {
+ Slog.v(TAG, "Finished reading blobs data");
+ }
} catch (Exception e) {
Slog.wtf(TAG, "Error reading blobs data", e);
}
@@ -614,6 +694,7 @@
if (session.getOwnerUid() == uid
&& session.getOwnerPackageName().equals(packageName)) {
session.getSessionFile().delete();
+ mKnownBlobIds.remove(session.getSessionId());
indicesToRemove.add(i);
}
}
@@ -633,6 +714,7 @@
// Delete the blob if it doesn't have any active leases.
if (!blobMetadata.hasLeases()) {
blobMetadata.getBlobFile().delete();
+ mKnownBlobIds.remove(blobMetadata.getBlobId());
indicesToRemove.add(i);
}
}
@@ -640,6 +722,10 @@
userBlobs.removeAt(indicesToRemove.get(i));
}
writeBlobsInfoAsync();
+ if (LOGV) {
+ Slog.v(TAG, "Removed blobs data associated with pkg="
+ + packageName + ", uid=" + uid);
+ }
}
}
@@ -651,6 +737,7 @@
for (int i = 0, count = userSessions.size(); i < count; ++i) {
final BlobStoreSession session = userSessions.valueAt(i);
session.getSessionFile().delete();
+ mKnownBlobIds.remove(session.getSessionId());
}
}
@@ -660,11 +747,107 @@
for (int i = 0, count = userBlobs.size(); i < count; ++i) {
final BlobMetadata blobMetadata = userBlobs.valueAt(i);
blobMetadata.getBlobFile().delete();
+ mKnownBlobIds.remove(blobMetadata.getBlobId());
}
}
+ if (LOGV) {
+ Slog.v(TAG, "Removed blobs data in user " + userId);
+ }
}
}
+ @GuardedBy("mBlobsLock")
+ @VisibleForTesting
+ void handleIdleMaintenanceLocked() {
+ // Cleanup any left over data on disk that is not part of index.
+ final ArrayList<Long> deletedBlobIds = new ArrayList<>();
+ final ArrayList<File> filesToDelete = new ArrayList<>();
+ final File blobsDir = BlobStoreConfig.getBlobsDir();
+ if (blobsDir.exists()) {
+ for (File file : blobsDir.listFiles()) {
+ try {
+ final long id = Long.parseLong(file.getName());
+ if (mKnownBlobIds.indexOf(id) < 0) {
+ filesToDelete.add(file);
+ deletedBlobIds.add(id);
+ }
+ } catch (NumberFormatException e) {
+ Slog.wtf(TAG, "Error parsing the file name: " + file, e);
+ filesToDelete.add(file);
+ }
+ }
+ for (int i = 0, count = filesToDelete.size(); i < count; ++i) {
+ filesToDelete.get(i).delete();
+ }
+ }
+
+ // Cleanup any stale blobs.
+ for (int i = 0, userCount = mBlobsMap.size(); i < userCount; ++i) {
+ final ArrayMap<BlobHandle, BlobMetadata> userBlobs = mBlobsMap.valueAt(i);
+ userBlobs.entrySet().removeIf(entry -> {
+ final BlobHandle blobHandle = entry.getKey();
+ final BlobMetadata blobMetadata = entry.getValue();
+ boolean shouldRemove = false;
+
+ // Cleanup expired data blobs.
+ if (blobHandle.isExpired()) {
+ shouldRemove = true;
+ }
+
+ // Cleanup blobs with no active leases.
+ // TODO: Exclude blobs which were just committed.
+ if (!blobMetadata.hasLeases()) {
+ shouldRemove = true;
+ }
+
+ if (shouldRemove) {
+ blobMetadata.getBlobFile().delete();
+ mKnownBlobIds.remove(blobMetadata.getBlobId());
+ deletedBlobIds.add(blobMetadata.getBlobId());
+ }
+ return shouldRemove;
+ });
+ }
+ writeBlobsInfoAsync();
+
+ // Cleanup any stale sessions.
+ final ArrayList<Integer> indicesToRemove = new ArrayList<>();
+ for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
+ final LongSparseArray<BlobStoreSession> userSessions = mSessions.valueAt(i);
+ indicesToRemove.clear();
+ for (int j = 0, sessionsCount = userSessions.size(); j < sessionsCount; ++j) {
+ final BlobStoreSession blobStoreSession = userSessions.valueAt(j);
+ boolean shouldRemove = false;
+
+ // Cleanup sessions which haven't been modified in a while.
+ if (blobStoreSession.getSessionFile().lastModified()
+ < System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MILLIS) {
+ shouldRemove = true;
+ }
+
+ // Cleanup sessions with already expired data.
+ if (blobStoreSession.getBlobHandle().isExpired()) {
+ shouldRemove = true;
+ }
+
+ if (shouldRemove) {
+ blobStoreSession.getSessionFile().delete();
+ mKnownBlobIds.remove(blobStoreSession.getSessionId());
+ indicesToRemove.add(j);
+ deletedBlobIds.add(blobStoreSession.getSessionId());
+ }
+ }
+ for (int j = 0; j < indicesToRemove.size(); ++j) {
+ userSessions.removeAt(indicesToRemove.get(j));
+ }
+ }
+ if (LOGV) {
+ Slog.v(TAG, "Completed idle maintenance; deleted "
+ + Arrays.toString(deletedBlobIds.toArray()));
+ }
+ writeBlobSessionsAsync();
+ }
+
void runClearAllSessions(@UserIdInt int userId) {
synchronized (mBlobsLock) {
if (userId == UserHandle.USER_ALL) {
@@ -727,10 +910,10 @@
fout.increaseIndent();
for (int j = 0, blobsCount = userBlobs.size(); j < blobsCount; ++j) {
final BlobMetadata blobMetadata = userBlobs.valueAt(j);
- if (!dumpArgs.shouldDumpBlob(blobMetadata.blobId)) {
+ if (!dumpArgs.shouldDumpBlob(blobMetadata.getBlobId())) {
continue;
}
- fout.println("Blob #" + blobMetadata.blobId);
+ fout.println("Blob #" + blobMetadata.getBlobId());
fout.increaseIndent();
blobMetadata.dump(fout, dumpArgs);
fout.decreaseIndent();
@@ -742,6 +925,9 @@
private class PackageChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ if (LOGV) {
+ Slog.v(TAG, "Received " + intent);
+ }
switch (intent.getAction()) {
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
case Intent.ACTION_PACKAGE_DATA_CLEARED:
@@ -893,6 +1079,14 @@
final DumpArgs dumpArgs = DumpArgs.parse(args);
final IndentingPrintWriter fout = new IndentingPrintWriter(writer, " ");
+ if (dumpArgs.shouldDumpHelp()) {
+ writer.println("dumpsys blob_store [options]:");
+ fout.increaseIndent();
+ dumpArgs.dumpArgsUsage(fout);
+ fout.decreaseIndent();
+ return;
+ }
+
synchronized (mBlobsLock) {
fout.println("mCurrentMaxSessionId: " + mCurrentMaxSessionId);
fout.println();
@@ -926,6 +1120,7 @@
private boolean mDumpOnlySelectedSections;
private boolean mDumpSessions;
private boolean mDumpBlobs;
+ private boolean mDumpHelp;
public boolean shouldDumpSession(String packageName, int uid, long blobId) {
if (!CollectionUtils.isEmpty(mDumpPackages)
@@ -971,6 +1166,10 @@
|| mDumpUserIds.indexOf(userId) >= 0;
}
+ public boolean shouldDumpHelp() {
+ return mDumpHelp;
+ }
+
private DumpArgs() {}
public static DumpArgs parse(String[] args) {
@@ -1000,6 +1199,8 @@
dumpArgs.mDumpUserIds.add(getIntArgRequired(args, ++i, "userId"));
} else if ("--blob".equals(opt) || "-b".equals(opt)) {
dumpArgs.mDumpBlobIds.add(getLongArgRequired(args, ++i, "blobId"));
+ } else if ("--help".equals(opt) || "-h".equals(opt)) {
+ dumpArgs.mDumpHelp = true;
} else {
// Everything else is assumed to be blob ids.
dumpArgs.mDumpBlobIds.add(getLongArgRequired(args, i, "blobId"));
@@ -1040,6 +1241,40 @@
}
return value;
}
+
+ private void dumpArgsUsage(IndentingPrintWriter pw) {
+ pw.println("--help | -h");
+ printWithIndent(pw, "Dump this help text");
+ pw.println("--sessions");
+ printWithIndent(pw, "Dump only the sessions info");
+ pw.println("--blobs");
+ printWithIndent(pw, "Dump only the committed blobs info");
+ pw.println("--package | -p [package-name]");
+ printWithIndent(pw, "Dump blobs info associated with the given package");
+ pw.println("--uid | -u [uid]");
+ printWithIndent(pw, "Dump blobs info associated with the given uid");
+ pw.println("--user [user-id]");
+ printWithIndent(pw, "Dump blobs info in the given user");
+ pw.println("--blob | -b [session-id | blob-id]");
+ printWithIndent(pw, "Dump blob info corresponding to the given ID");
+ pw.println("--full | -f");
+ printWithIndent(pw, "Dump full unredacted blobs data");
+ }
+
+ private void printWithIndent(IndentingPrintWriter pw, String str) {
+ pw.increaseIndent();
+ pw.println(str);
+ pw.decreaseIndent();
+ }
+ }
+
+ private class LocalService extends BlobStoreManagerInternal {
+ @Override
+ public void onIdleMaintenance() {
+ synchronized (mBlobsLock) {
+ handleIdleMaintenanceLocked();
+ }
+ }
}
@VisibleForTesting
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index 54a2997..bd35b86 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -21,11 +21,13 @@
import static android.app.blob.XmlTags.ATTR_UID;
import static android.app.blob.XmlTags.TAG_ACCESS_MODE;
import static android.app.blob.XmlTags.TAG_BLOB_HANDLE;
+import static android.os.Trace.TRACE_TAG_SYSTEM_SERVER;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_RDWR;
import static android.system.OsConstants.SEEK_SET;
+import static com.android.server.blob.BlobStoreConfig.LOGV;
import static com.android.server.blob.BlobStoreConfig.TAG;
import android.annotation.BytesLong;
@@ -40,6 +42,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
+import android.os.Trace;
import android.os.storage.StorageManager;
import android.system.ErrnoException;
import android.system.Os;
@@ -381,15 +384,22 @@
void verifyBlobData() {
byte[] actualDigest = null;
try {
+ Trace.traceBegin(TRACE_TAG_SYSTEM_SERVER,
+ "computeBlobDigest-i" + mSessionId + "-l" + getSessionFile().length());
actualDigest = FileUtils.digest(getSessionFile(), mBlobHandle.algorithm);
} catch (IOException | NoSuchAlgorithmException e) {
Slog.e(TAG, "Error computing the digest", e);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_SYSTEM_SERVER);
}
synchronized (mSessionLock) {
if (actualDigest != null && Arrays.equals(actualDigest, mBlobHandle.digest)) {
mState = STATE_VERIFIED_VALID;
// Commit callback will be sent once the data is persisted.
} else {
+ if (LOGV) {
+ Slog.v(TAG, "Digest of the data didn't match the given BlobHandle.digest");
+ }
mState = STATE_VERIFIED_INVALID;
sendCommitCallbackResult(COMMIT_RESULT_ERROR);
}
@@ -447,6 +457,16 @@
}
}
+ @Override
+ public String toString() {
+ return "BlobStoreSession {"
+ + "id:" + mSessionId
+ + ",handle:" + mBlobHandle
+ + ",uid:" + mOwnerUid
+ + ",pkg:" + mOwnerPackageName
+ + "}";
+ }
+
private void assertCallerIsOwner() {
final int callingUid = Binder.getCallingUid();
if (callingUid != mOwnerUid) {
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 4b1ba02..16c0910 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -48,6 +48,8 @@
void clearData(String pkg, int uid, boolean fromApp);
void enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration, int displayId, @nullable ITransientNotificationCallback callback);
void enqueueToast(String pkg, IBinder token, ITransientNotification callback, int duration, int displayId);
+ // TODO(b/144152069): Remove this after assessing impact on dogfood.
+ void enqueueTextOrCustomToast(String pkg, IBinder token, ITransientNotification callback, int duration, int displayId, boolean isCustom);
void cancelToast(String pkg, IBinder token);
void finishToken(String pkg, IBinder token);
diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl
index de8f470..5ead0c9 100644
--- a/core/java/android/app/timedetector/ITimeDetectorService.aidl
+++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl
@@ -18,7 +18,7 @@
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
/**
* System private API to communicate with time detector service.
@@ -34,7 +34,7 @@
* {@hide}
*/
interface ITimeDetectorService {
- void suggestPhoneTime(in PhoneTimeSuggestion timeSuggestion);
void suggestManualTime(in ManualTimeSuggestion timeSuggestion);
void suggestNetworkTime(in NetworkTimeSuggestion timeSuggestion);
+ void suggestTelephonyTime(in TelephonyTimeSuggestion timeSuggestion);
}
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.aidl b/core/java/android/app/timedetector/TelephonyTimeSuggestion.aidl
similarity index 94%
rename from core/java/android/app/timedetector/PhoneTimeSuggestion.aidl
rename to core/java/android/app/timedetector/TelephonyTimeSuggestion.aidl
index f5e2405..d9b0386 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.aidl
+++ b/core/java/android/app/timedetector/TelephonyTimeSuggestion.aidl
@@ -16,4 +16,4 @@
package android.app.timedetector;
-parcelable PhoneTimeSuggestion;
+parcelable TelephonyTimeSuggestion;
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
similarity index 79%
rename from core/java/android/app/timedetector/PhoneTimeSuggestion.java
rename to core/java/android/app/timedetector/TelephonyTimeSuggestion.java
index 0133a44..c0e8957 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.java
+++ b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
@@ -50,17 +50,17 @@
*
* @hide
*/
-public final class PhoneTimeSuggestion implements Parcelable {
+public final class TelephonyTimeSuggestion implements Parcelable {
/** @hide */
- public static final @NonNull Parcelable.Creator<PhoneTimeSuggestion> CREATOR =
- new Parcelable.Creator<PhoneTimeSuggestion>() {
- public PhoneTimeSuggestion createFromParcel(Parcel in) {
- return PhoneTimeSuggestion.createFromParcel(in);
+ public static final @NonNull Parcelable.Creator<TelephonyTimeSuggestion> CREATOR =
+ new Parcelable.Creator<TelephonyTimeSuggestion>() {
+ public TelephonyTimeSuggestion createFromParcel(Parcel in) {
+ return TelephonyTimeSuggestion.createFromParcel(in);
}
- public PhoneTimeSuggestion[] newArray(int size) {
- return new PhoneTimeSuggestion[size];
+ public TelephonyTimeSuggestion[] newArray(int size) {
+ return new TelephonyTimeSuggestion[size];
}
};
@@ -68,15 +68,15 @@
@Nullable private final TimestampedValue<Long> mUtcTime;
@Nullable private ArrayList<String> mDebugInfo;
- private PhoneTimeSuggestion(Builder builder) {
+ private TelephonyTimeSuggestion(Builder builder) {
mSlotIndex = builder.mSlotIndex;
mUtcTime = builder.mUtcTime;
mDebugInfo = builder.mDebugInfo != null ? new ArrayList<>(builder.mDebugInfo) : null;
}
- private static PhoneTimeSuggestion createFromParcel(Parcel in) {
+ private static TelephonyTimeSuggestion createFromParcel(Parcel in) {
int slotIndex = in.readInt();
- PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion.Builder(slotIndex)
+ TelephonyTimeSuggestion suggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
.setUtcTime(in.readParcelable(null /* classLoader */))
.build();
@SuppressWarnings("unchecked")
@@ -102,7 +102,7 @@
/**
* Returns an identifier for the source of this suggestion.
*
- * <p>See {@link PhoneTimeSuggestion} for more information about {@code slotIndex}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code slotIndex}.
*/
public int getSlotIndex() {
return mSlotIndex;
@@ -111,7 +111,7 @@
/**
* Returns the suggested time or {@code null} if there isn't one.
*
- * <p>See {@link PhoneTimeSuggestion} for more information about {@code utcTime}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code utcTime}.
*/
@Nullable
public TimestampedValue<Long> getUtcTime() {
@@ -121,7 +121,7 @@
/**
* Returns debug metadata for the suggestion.
*
- * <p>See {@link PhoneTimeSuggestion} for more information about {@code debugInfo}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code debugInfo}.
*/
@NonNull
public List<String> getDebugInfo() {
@@ -132,7 +132,7 @@
/**
* Associates information with the instance that can be useful for debugging / logging.
*
- * <p>See {@link PhoneTimeSuggestion} for more information about {@code debugInfo}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code debugInfo}.
*/
public void addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
@@ -144,7 +144,7 @@
/**
* Associates information with the instance that can be useful for debugging / logging.
*
- * <p>See {@link PhoneTimeSuggestion} for more information about {@code debugInfo}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code debugInfo}.
*/
public void addDebugInfo(@NonNull List<String> debugInfo) {
if (mDebugInfo == null) {
@@ -161,7 +161,7 @@
if (o == null || getClass() != o.getClass()) {
return false;
}
- PhoneTimeSuggestion that = (PhoneTimeSuggestion) o;
+ TelephonyTimeSuggestion that = (TelephonyTimeSuggestion) o;
return mSlotIndex == that.mSlotIndex
&& Objects.equals(mUtcTime, that.mUtcTime);
}
@@ -173,7 +173,7 @@
@Override
public String toString() {
- return "PhoneTimeSuggestion{"
+ return "TelephonyTimeSuggestion{"
+ "mSlotIndex='" + mSlotIndex + '\''
+ ", mUtcTime=" + mUtcTime
+ ", mDebugInfo=" + mDebugInfo
@@ -181,7 +181,7 @@
}
/**
- * Builds {@link PhoneTimeSuggestion} instances.
+ * Builds {@link TelephonyTimeSuggestion} instances.
*
* @hide
*/
@@ -193,7 +193,7 @@
/**
* Creates a builder with the specified {@code slotIndex}.
*
- * <p>See {@link PhoneTimeSuggestion} for more information about {@code slotIndex}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code slotIndex}.
*/
public Builder(int slotIndex) {
mSlotIndex = slotIndex;
@@ -202,7 +202,7 @@
/**
* Returns the builder for call chaining.
*
- * <p>See {@link PhoneTimeSuggestion} for more information about {@code utcTime}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code utcTime}.
*/
@NonNull
public Builder setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
@@ -218,7 +218,7 @@
/**
* Returns the builder for call chaining.
*
- * <p>See {@link PhoneTimeSuggestion} for more information about {@code debugInfo}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code debugInfo}.
*/
@NonNull
public Builder addDebugInfo(@NonNull String debugInfo) {
@@ -229,10 +229,10 @@
return this;
}
- /** Returns the {@link PhoneTimeSuggestion}. */
+ /** Returns the {@link TelephonyTimeSuggestion}. */
@NonNull
- public PhoneTimeSuggestion build() {
- return new PhoneTimeSuggestion(this);
+ public TelephonyTimeSuggestion build() {
+ return new TelephonyTimeSuggestion(this);
}
}
}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index df4f513..84ad495 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -45,12 +45,12 @@
}
/**
- * Suggests the current phone-signal derived time to the detector. The detector may ignore the
- * signal if better signals are available such as those that come from more reliable sources or
- * were determined more recently.
+ * Suggests a telephony-signal derived time to the detector. The detector may ignore the signal
+ * if better signals are available such as those that come from more reliable sources or were
+ * determined more recently.
*/
- @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE)
- void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion);
+ @RequiresPermission(android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE)
+ void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion);
/**
* Suggests the user's manually entered current time to the detector.
diff --git a/core/java/android/app/timedetector/TimeDetectorImpl.java b/core/java/android/app/timedetector/TimeDetectorImpl.java
index 1683817..c1d6667 100644
--- a/core/java/android/app/timedetector/TimeDetectorImpl.java
+++ b/core/java/android/app/timedetector/TimeDetectorImpl.java
@@ -40,12 +40,12 @@
}
@Override
- public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
+ public void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion) {
if (DEBUG) {
- Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion);
+ Log.d(TAG, "suggestTelephonyTime called: " + timeSuggestion);
}
try {
- mITimeDetectorService.suggestPhoneTime(timeSuggestion);
+ mITimeDetectorService.suggestTelephonyTime(timeSuggestion);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl b/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl
index df643831..b06f4b8 100644
--- a/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl
+++ b/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl
@@ -17,7 +17,7 @@
package android.app.timezonedetector;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
/**
* System private API to communicate with time zone detector service.
@@ -34,5 +34,5 @@
*/
interface ITimeZoneDetectorService {
void suggestManualTimeZone(in ManualTimeZoneSuggestion timeZoneSuggestion);
- void suggestPhoneTimeZone(in PhoneTimeZoneSuggestion timeZoneSuggestion);
+ void suggestTelephonyTimeZone(in TelephonyTimeZoneSuggestion timeZoneSuggestion);
}
diff --git a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.aidl b/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.aidl
similarity index 94%
rename from core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.aidl
rename to core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.aidl
index 3ad903b..b57ad20 100644
--- a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.aidl
+++ b/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.aidl
@@ -16,4 +16,4 @@
package android.app.timezonedetector;
-parcelable PhoneTimeZoneSuggestion;
+parcelable TelephonyTimeZoneSuggestion;
diff --git a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
similarity index 84%
rename from core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
rename to core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
index 9147b44..150c01d 100644
--- a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
@@ -56,18 +56,18 @@
*
* @hide
*/
-public final class PhoneTimeZoneSuggestion implements Parcelable {
+public final class TelephonyTimeZoneSuggestion implements Parcelable {
/** @hide */
@NonNull
- public static final Creator<PhoneTimeZoneSuggestion> CREATOR =
- new Creator<PhoneTimeZoneSuggestion>() {
- public PhoneTimeZoneSuggestion createFromParcel(Parcel in) {
- return PhoneTimeZoneSuggestion.createFromParcel(in);
+ public static final Creator<TelephonyTimeZoneSuggestion> CREATOR =
+ new Creator<TelephonyTimeZoneSuggestion>() {
+ public TelephonyTimeZoneSuggestion createFromParcel(Parcel in) {
+ return TelephonyTimeZoneSuggestion.createFromParcel(in);
}
- public PhoneTimeZoneSuggestion[] newArray(int size) {
- return new PhoneTimeZoneSuggestion[size];
+ public TelephonyTimeZoneSuggestion[] newArray(int size) {
+ return new TelephonyTimeZoneSuggestion[size];
}
};
@@ -76,7 +76,7 @@
* the same {@code slotIndex}.
*/
@NonNull
- public static PhoneTimeZoneSuggestion createEmptySuggestion(
+ public static TelephonyTimeZoneSuggestion createEmptySuggestion(
int slotIndex, @NonNull String debugInfo) {
return new Builder(slotIndex).addDebugInfo(debugInfo).build();
}
@@ -144,7 +144,7 @@
@Quality private final int mQuality;
@Nullable private List<String> mDebugInfo;
- private PhoneTimeZoneSuggestion(Builder builder) {
+ private TelephonyTimeZoneSuggestion(Builder builder) {
mSlotIndex = builder.mSlotIndex;
mZoneId = builder.mZoneId;
mMatchType = builder.mMatchType;
@@ -153,15 +153,16 @@
}
@SuppressWarnings("unchecked")
- private static PhoneTimeZoneSuggestion createFromParcel(Parcel in) {
+ private static TelephonyTimeZoneSuggestion createFromParcel(Parcel in) {
// Use the Builder so we get validation during build().
int slotIndex = in.readInt();
- PhoneTimeZoneSuggestion suggestion = new Builder(slotIndex)
+ TelephonyTimeZoneSuggestion suggestion = new Builder(slotIndex)
.setZoneId(in.readString())
.setMatchType(in.readInt())
.setQuality(in.readInt())
.build();
- List<String> debugInfo = in.readArrayList(PhoneTimeZoneSuggestion.class.getClassLoader());
+ List<String> debugInfo =
+ in.readArrayList(TelephonyTimeZoneSuggestion.class.getClassLoader());
if (debugInfo != null) {
suggestion.addDebugInfo(debugInfo);
}
@@ -185,7 +186,7 @@
/**
* Returns an identifier for the source of this suggestion.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code slotIndex}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code slotIndex}.
*/
public int getSlotIndex() {
return mSlotIndex;
@@ -195,7 +196,7 @@
* Returns the suggested time zone Olson ID, e.g. "America/Los_Angeles". {@code null} means that
* the caller is no longer sure what the current time zone is.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code zoneId}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code zoneId}.
*/
@Nullable
public String getZoneId() {
@@ -206,7 +207,7 @@
* Returns information about how the suggestion was determined which could be used to rank
* suggestions when several are available from different sources.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code matchType}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code matchType}.
*/
@MatchType
public int getMatchType() {
@@ -216,7 +217,7 @@
/**
* Returns information about the likelihood of the suggested zone being correct.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code quality}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code quality}.
*/
@Quality
public int getQuality() {
@@ -226,7 +227,7 @@
/**
* Returns debug metadata for the suggestion.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code debugInfo}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code debugInfo}.
*/
@NonNull
public List<String> getDebugInfo() {
@@ -237,7 +238,7 @@
/**
* Associates information with the instance that can be useful for debugging / logging.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code debugInfo}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code debugInfo}.
*/
public void addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
@@ -249,7 +250,7 @@
/**
* Associates information with the instance that can be useful for debugging / logging.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code debugInfo}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code debugInfo}.
*/
public void addDebugInfo(@NonNull List<String> debugInfo) {
if (mDebugInfo == null) {
@@ -266,7 +267,7 @@
if (o == null || getClass() != o.getClass()) {
return false;
}
- PhoneTimeZoneSuggestion that = (PhoneTimeZoneSuggestion) o;
+ TelephonyTimeZoneSuggestion that = (TelephonyTimeZoneSuggestion) o;
return mSlotIndex == that.mSlotIndex
&& mMatchType == that.mMatchType
&& mQuality == that.mQuality
@@ -280,7 +281,7 @@
@Override
public String toString() {
- return "PhoneTimeZoneSuggestion{"
+ return "TelephonyTimeZoneSuggestion{"
+ "mSlotIndex=" + mSlotIndex
+ ", mZoneId='" + mZoneId + '\''
+ ", mMatchType=" + mMatchType
@@ -290,7 +291,7 @@
}
/**
- * Builds {@link PhoneTimeZoneSuggestion} instances.
+ * Builds {@link TelephonyTimeZoneSuggestion} instances.
*
* @hide
*/
@@ -304,7 +305,7 @@
/**
* Creates a builder with the specified {@code slotIndex}.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code slotIndex}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code slotIndex}.
*/
public Builder(int slotIndex) {
mSlotIndex = slotIndex;
@@ -313,7 +314,7 @@
/**
* Returns the builder for call chaining.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code zoneId}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code zoneId}.
*/
@NonNull
public Builder setZoneId(@Nullable String zoneId) {
@@ -324,7 +325,7 @@
/**
* Returns the builder for call chaining.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code matchType}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code matchType}.
*/
@NonNull
public Builder setMatchType(@MatchType int matchType) {
@@ -335,7 +336,7 @@
/**
* Returns the builder for call chaining.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code quality}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code quality}.
*/
@NonNull
public Builder setQuality(@Quality int quality) {
@@ -346,7 +347,7 @@
/**
* Returns the builder for call chaining.
*
- * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code debugInfo}.
+ * <p>See {@link TelephonyTimeZoneSuggestion} for more information about {@code debugInfo}.
*/
@NonNull
public Builder addDebugInfo(@NonNull String debugInfo) {
@@ -384,11 +385,11 @@
}
}
- /** Returns the {@link PhoneTimeZoneSuggestion}. */
+ /** Returns the {@link TelephonyTimeZoneSuggestion}. */
@NonNull
- public PhoneTimeZoneSuggestion build() {
+ public TelephonyTimeZoneSuggestion build() {
validate();
- return new PhoneTimeZoneSuggestion(this);
+ return new TelephonyTimeZoneSuggestion(this);
}
}
}
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index 6a3953e..20761ad 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -47,8 +47,8 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE)
- void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion);
+ @RequiresPermission(android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE)
+ void suggestTelephonyTimeZone(@NonNull TelephonyTimeZoneSuggestion timeZoneSuggestion);
/**
* Suggests the current time zone, determined for the user's manually information, to the
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java b/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java
index 27b8374..0ada885 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java
@@ -40,12 +40,12 @@
}
@Override
- public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) {
+ public void suggestTelephonyTimeZone(@NonNull TelephonyTimeZoneSuggestion timeZoneSuggestion) {
if (DEBUG) {
- Log.d(TAG, "suggestPhoneTimeZone called: " + timeZoneSuggestion);
+ Log.d(TAG, "suggestTelephonyTimeZone called: " + timeZoneSuggestion);
}
try {
- mITimeZoneDetectorService.suggestPhoneTimeZone(timeZoneSuggestion);
+ mITimeZoneDetectorService.suggestTelephonyTimeZone(timeZoneSuggestion);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 0549c34..6f30ecd 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -15,5 +15,15 @@
"name": "FrameworksInstantAppResolverTests",
"file_patterns": ["(/|^)InstantApp[^/]*"]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsAppSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.appsecurity.cts.AppSecurityTests#testPermissionDiffCert"
+ }
+ ]
+ }
]
}
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index db714c2..a2c70b9 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -148,6 +148,9 @@
@Nullable
private CharSequence mText;
+ // TODO(b/144152069): Remove this after assessing impact on dogfood.
+ private boolean mIsCustomToast;
+
/**
* Construct an empty Toast object. You must call {@link #setView} before you
* can call {@link #show}.
@@ -214,7 +217,8 @@
service.enqueueTextToast(pkg, mToken, mText, mDuration, displayId, callback);
}
} else {
- service.enqueueToast(pkg, mToken, tn, mDuration, displayId);
+ service.enqueueTextOrCustomToast(pkg, mToken, tn, mDuration, displayId,
+ mIsCustomToast);
}
} catch (RemoteException e) {
// Empty
@@ -252,12 +256,17 @@
*/
@Deprecated
public void setView(View view) {
+ mIsCustomToast = true;
mNextView = view;
}
/**
* Return the view.
*
+ * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
+ * targeting API level {@link Build.VERSION_CODES#R} or higher that haven't called {@link
+ * #setView(View)} with a non-{@code null} view, this method will return {@code null}.
+ *
* @see #setView
* @deprecated Custom toast views are deprecated. Apps can create a standard text toast with the
* {@link #makeText(Context, CharSequence, int)} method, or use a
@@ -293,6 +302,10 @@
/**
* Set the margins of the view.
*
+ * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
+ * targeting API level {@link Build.VERSION_CODES#R} or higher, this method is a no-op when
+ * called on text toasts.
+ *
* @param horizontalMargin The horizontal margin, in percentage of the
* container width, between the container's edges and the
* notification
@@ -301,30 +314,59 @@
* notification
*/
public void setMargin(float horizontalMargin, float verticalMargin) {
+ if (isSystemRenderedTextToast()) {
+ Log.e(TAG, "setMargin() shouldn't be called on text toasts, the values won't be used");
+ }
mTN.mHorizontalMargin = horizontalMargin;
mTN.mVerticalMargin = verticalMargin;
}
/**
* Return the horizontal margin.
+ *
+ * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
+ * targeting API level {@link Build.VERSION_CODES#R} or higher, this method shouldn't be called
+ * on text toasts as its return value may not reflect actual value since text toasts are not
+ * rendered by the app anymore.
*/
public float getHorizontalMargin() {
+ if (isSystemRenderedTextToast()) {
+ Log.e(TAG, "getHorizontalMargin() shouldn't be called on text toasts, the result may "
+ + "not reflect actual values.");
+ }
return mTN.mHorizontalMargin;
}
/**
* Return the vertical margin.
+ *
+ * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
+ * targeting API level {@link Build.VERSION_CODES#R} or higher, this method shouldn't be called
+ * on text toasts as its return value may not reflect actual value since text toasts are not
+ * rendered by the app anymore.
*/
public float getVerticalMargin() {
+ if (isSystemRenderedTextToast()) {
+ Log.e(TAG, "getVerticalMargin() shouldn't be called on text toasts, the result may not"
+ + " reflect actual values.");
+ }
return mTN.mVerticalMargin;
}
/**
* Set the location at which the notification should appear on the screen.
+ *
+ * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
+ * targeting API level {@link Build.VERSION_CODES#R} or higher, this method is a no-op when
+ * called on text toasts.
+ *
* @see android.view.Gravity
* @see #getGravity
*/
public void setGravity(int gravity, int xOffset, int yOffset) {
+ if (isSystemRenderedTextToast()) {
+ Log.e(TAG, "setGravity() shouldn't be called on text toasts, the values won't be used");
+ }
mTN.mGravity = gravity;
mTN.mX = xOffset;
mTN.mY = yOffset;
@@ -332,27 +374,59 @@
/**
* Get the location at which the notification should appear on the screen.
+ *
+ * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
+ * targeting API level {@link Build.VERSION_CODES#R} or higher, this method shouldn't be called
+ * on text toasts as its return value may not reflect actual value since text toasts are not
+ * rendered by the app anymore.
+ *
* @see android.view.Gravity
* @see #getGravity
*/
public int getGravity() {
+ if (isSystemRenderedTextToast()) {
+ Log.e(TAG, "getGravity() shouldn't be called on text toasts, the result may not reflect"
+ + " actual values.");
+ }
return mTN.mGravity;
}
/**
* Return the X offset in pixels to apply to the gravity's location.
+ *
+ * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
+ * targeting API level {@link Build.VERSION_CODES#R} or higher, this method shouldn't be called
+ * on text toasts as its return value may not reflect actual value since text toasts are not
+ * rendered by the app anymore.
*/
public int getXOffset() {
+ if (isSystemRenderedTextToast()) {
+ Log.e(TAG, "getXOffset() shouldn't be called on text toasts, the result may not reflect"
+ + " actual values.");
+ }
return mTN.mX;
}
/**
* Return the Y offset in pixels to apply to the gravity's location.
+ *
+ * <p><strong>Warning:</strong> Starting from Android {@link Build.VERSION_CODES#R}, for apps
+ * targeting API level {@link Build.VERSION_CODES#R} or higher, this method shouldn't be called
+ * on text toasts as its return value may not reflect actual value since text toasts are not
+ * rendered by the app anymore.
*/
public int getYOffset() {
+ if (isSystemRenderedTextToast()) {
+ Log.e(TAG, "getYOffset() shouldn't be called on text toasts, the result may not reflect"
+ + " actual values.");
+ }
return mTN.mY;
}
+ private boolean isSystemRenderedTextToast() {
+ return Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM) && mNextView == null;
+ }
+
/**
* Adds a callback to be notified when the toast is shown or hidden.
*
@@ -386,7 +460,7 @@
}
/**
- * Make a standard toast that just contains a text view.
+ * Make a standard toast that just contains text.
*
* @param context The context to use. Usually your {@link android.app.Application}
* or {@link android.app.Activity} object.
@@ -429,7 +503,7 @@
}
/**
- * Make a standard toast that just contains a text view with the text from a resource.
+ * Make a standard toast that just contains text from a resource.
*
* @param context The context to use. Usually your {@link android.app.Application}
* or {@link android.app.Activity} object.
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 9758673..35eb0fc 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -208,6 +208,7 @@
static_libs: [
"libasync_safe",
+ "libbinderthreadstateutils",
"libdmabufinfo",
"libgif",
"libseccomp_policy",
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index c269d1c..14d7487 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -37,6 +37,7 @@
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/Stability.h>
+#include <binderthreadstate/CallerUtils.h>
#include <cutils/atomic.h>
#include <log/log.h>
#include <utils/KeyedVector.h>
@@ -950,7 +951,7 @@
static jboolean android_os_Binder_isHandlingTransaction()
{
- return IPCThreadState::self()->isServingCall();
+ return getCurrentServingCall() == BinderCallType::BINDER;
}
static jlong android_os_Binder_clearCallingIdentity()
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 27d41d4..32a6cc3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2605,7 +2605,7 @@
<p>Not for use by third-party applications.
@hide
-->
- <permission android:name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"
+ <permission android:name="android.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE"
android:protectionLevel="signature|telephony" />
<!-- Allows applications like settings to suggest the user's manually chosen time / time zone.
@@ -5328,6 +5328,10 @@
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
+ <service android:name="com.android.server.blob.BlobStoreIdleJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
<service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader">
<intent-filter>
<action android:name="android.intent.action.LOAD_DATA" />
diff --git a/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
similarity index 66%
rename from core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
rename to core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
index d17b635..4b64dfc 100644
--- a/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
@@ -26,44 +26,45 @@
import org.junit.Test;
-public class PhoneTimeSuggestionTest {
+public class TelephonyTimeSuggestionTest {
private static final int SLOT_INDEX = 99999;
@Test
public void testEquals() {
- PhoneTimeSuggestion.Builder builder1 = new PhoneTimeSuggestion.Builder(SLOT_INDEX);
+ TelephonyTimeSuggestion.Builder builder1 = new TelephonyTimeSuggestion.Builder(SLOT_INDEX);
{
- PhoneTimeSuggestion one = builder1.build();
+ TelephonyTimeSuggestion one = builder1.build();
assertEquals(one, one);
}
- PhoneTimeSuggestion.Builder builder2 = new PhoneTimeSuggestion.Builder(SLOT_INDEX);
+ TelephonyTimeSuggestion.Builder builder2 = new TelephonyTimeSuggestion.Builder(SLOT_INDEX);
{
- PhoneTimeSuggestion one = builder1.build();
- PhoneTimeSuggestion two = builder2.build();
+ TelephonyTimeSuggestion one = builder1.build();
+ TelephonyTimeSuggestion two = builder2.build();
assertEquals(one, two);
assertEquals(two, one);
}
builder1.setUtcTime(new TimestampedValue<>(1111L, 2222L));
{
- PhoneTimeSuggestion one = builder1.build();
+ TelephonyTimeSuggestion one = builder1.build();
assertEquals(one, one);
}
builder2.setUtcTime(new TimestampedValue<>(1111L, 2222L));
{
- PhoneTimeSuggestion one = builder1.build();
- PhoneTimeSuggestion two = builder2.build();
+ TelephonyTimeSuggestion one = builder1.build();
+ TelephonyTimeSuggestion two = builder2.build();
assertEquals(one, two);
assertEquals(two, one);
}
- PhoneTimeSuggestion.Builder builder3 = new PhoneTimeSuggestion.Builder(SLOT_INDEX + 1);
+ TelephonyTimeSuggestion.Builder builder3 =
+ new TelephonyTimeSuggestion.Builder(SLOT_INDEX + 1);
builder3.setUtcTime(new TimestampedValue<>(1111L, 2222L));
{
- PhoneTimeSuggestion one = builder1.build();
- PhoneTimeSuggestion three = builder3.build();
+ TelephonyTimeSuggestion one = builder1.build();
+ TelephonyTimeSuggestion three = builder3.build();
assertNotEquals(one, three);
assertNotEquals(three, one);
}
@@ -72,15 +73,15 @@
builder1.addDebugInfo("Debug info 1");
builder2.addDebugInfo("Debug info 2");
{
- PhoneTimeSuggestion one = builder1.build();
- PhoneTimeSuggestion two = builder2.build();
+ TelephonyTimeSuggestion one = builder1.build();
+ TelephonyTimeSuggestion two = builder2.build();
assertEquals(one, two);
}
}
@Test
public void testParcelable() {
- PhoneTimeSuggestion.Builder builder = new PhoneTimeSuggestion.Builder(SLOT_INDEX);
+ TelephonyTimeSuggestion.Builder builder = new TelephonyTimeSuggestion.Builder(SLOT_INDEX);
assertRoundTripParcelable(builder.build());
builder.setUtcTime(new TimestampedValue<>(1111L, 2222L));
@@ -88,9 +89,9 @@
// DebugInfo should also be stored (but is not checked by equals()
{
- PhoneTimeSuggestion suggestion1 = builder.build();
+ TelephonyTimeSuggestion suggestion1 = builder.build();
builder.addDebugInfo("This is debug info");
- PhoneTimeSuggestion rtSuggestion1 = roundTripParcelable(suggestion1);
+ TelephonyTimeSuggestion rtSuggestion1 = roundTripParcelable(suggestion1);
assertEquals(suggestion1.getDebugInfo(), rtSuggestion1.getDebugInfo());
}
}
diff --git a/core/tests/coretests/src/android/app/timezonedetector/PhoneTimeZoneSuggestionTest.java b/core/tests/coretests/src/android/app/timezonedetector/PhoneTimeZoneSuggestionTest.java
deleted file mode 100644
index 384dbf9..0000000
--- a/core/tests/coretests/src/android/app/timezonedetector/PhoneTimeZoneSuggestionTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 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.app.timezonedetector;
-
-import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
-import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-public class PhoneTimeZoneSuggestionTest {
- private static final int SLOT_INDEX = 99999;
-
- @Test
- public void testEquals() {
- PhoneTimeZoneSuggestion.Builder builder1 = new PhoneTimeZoneSuggestion.Builder(SLOT_INDEX);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- assertEquals(one, one);
- }
-
- PhoneTimeZoneSuggestion.Builder builder2 = new PhoneTimeZoneSuggestion.Builder(SLOT_INDEX);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- assertEquals(one, two);
- assertEquals(two, one);
- }
-
- PhoneTimeZoneSuggestion.Builder builder3 =
- new PhoneTimeZoneSuggestion.Builder(SLOT_INDEX + 1);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion three = builder3.build();
- assertNotEquals(one, three);
- assertNotEquals(three, one);
- }
-
- builder1.setZoneId("Europe/London");
- builder1.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
- builder1.setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- assertNotEquals(one, two);
- }
-
- builder2.setZoneId("Europe/Paris");
- builder2.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
- builder2.setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- assertNotEquals(one, two);
- }
-
- builder1.setZoneId("Europe/Paris");
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- assertEquals(one, two);
- }
-
- builder1.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID);
- builder2.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- assertNotEquals(one, two);
- }
-
- builder1.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- assertEquals(one, two);
- }
-
- builder1.setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
- builder2.setQuality(PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- assertNotEquals(one, two);
- }
-
- builder1.setQuality(PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- assertEquals(one, two);
- }
-
- // DebugInfo must not be considered in equals().
- {
- PhoneTimeZoneSuggestion one = builder1.build();
- PhoneTimeZoneSuggestion two = builder2.build();
- one.addDebugInfo("Debug info 1");
- two.addDebugInfo("Debug info 2");
- assertEquals(one, two);
- }
- }
-
- @Test(expected = RuntimeException.class)
- public void testBuilderValidates_emptyZone_badMatchType() {
- PhoneTimeZoneSuggestion.Builder builder = new PhoneTimeZoneSuggestion.Builder(SLOT_INDEX);
- // No zone ID, so match type should be left unset.
- builder.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET);
- builder.build();
- }
-
- @Test(expected = RuntimeException.class)
- public void testBuilderValidates_zoneSet_badMatchType() {
- PhoneTimeZoneSuggestion.Builder builder = new PhoneTimeZoneSuggestion.Builder(SLOT_INDEX);
- builder.setZoneId("Europe/London");
- builder.setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
- builder.build();
- }
-
- @Test
- public void testParcelable() {
- PhoneTimeZoneSuggestion.Builder builder = new PhoneTimeZoneSuggestion.Builder(SLOT_INDEX);
- assertRoundTripParcelable(builder.build());
-
- builder.setZoneId("Europe/London");
- builder.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID);
- builder.setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
- PhoneTimeZoneSuggestion suggestion1 = builder.build();
- assertRoundTripParcelable(suggestion1);
-
- // DebugInfo should also be stored (but is not checked by equals()
- String debugString = "This is debug info";
- suggestion1.addDebugInfo(debugString);
- PhoneTimeZoneSuggestion suggestion1_2 = roundTripParcelable(suggestion1);
- assertEquals(suggestion1, suggestion1_2);
- assertTrue(suggestion1_2.getDebugInfo().contains(debugString));
- }
-}
diff --git a/core/tests/coretests/src/android/app/timezonedetector/TelephonyTimeZoneSuggestionTest.java b/core/tests/coretests/src/android/app/timezonedetector/TelephonyTimeZoneSuggestionTest.java
new file mode 100644
index 0000000..59d55b7
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezonedetector/TelephonyTimeZoneSuggestionTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 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.app.timezonedetector;
+
+import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
+import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class TelephonyTimeZoneSuggestionTest {
+ private static final int SLOT_INDEX = 99999;
+
+ @Test
+ public void testEquals() {
+ TelephonyTimeZoneSuggestion.Builder builder1 =
+ new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ assertEquals(one, one);
+ }
+
+ TelephonyTimeZoneSuggestion.Builder builder2 =
+ new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ assertEquals(one, two);
+ assertEquals(two, one);
+ }
+
+ TelephonyTimeZoneSuggestion.Builder builder3 =
+ new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX + 1);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion three = builder3.build();
+ assertNotEquals(one, three);
+ assertNotEquals(three, one);
+ }
+
+ builder1.setZoneId("Europe/London");
+ builder1.setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
+ builder1.setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder2.setZoneId("Europe/Paris");
+ builder2.setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
+ builder2.setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setZoneId("Europe/Paris");
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ assertEquals(one, two);
+ }
+
+ builder1.setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID);
+ builder2.setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ assertEquals(one, two);
+ }
+
+ builder1.setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
+ builder2.setQuality(
+ TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setQuality(
+ TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ assertEquals(one, two);
+ }
+
+ // DebugInfo must not be considered in equals().
+ {
+ TelephonyTimeZoneSuggestion one = builder1.build();
+ TelephonyTimeZoneSuggestion two = builder2.build();
+ one.addDebugInfo("Debug info 1");
+ two.addDebugInfo("Debug info 2");
+ assertEquals(one, two);
+ }
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testBuilderValidates_emptyZone_badMatchType() {
+ TelephonyTimeZoneSuggestion.Builder builder =
+ new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX);
+ // No zone ID, so match type should be left unset.
+ builder.setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET);
+ builder.build();
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testBuilderValidates_zoneSet_badMatchType() {
+ TelephonyTimeZoneSuggestion.Builder builder =
+ new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX);
+ builder.setZoneId("Europe/London");
+ builder.setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
+ builder.build();
+ }
+
+ @Test
+ public void testParcelable() {
+ TelephonyTimeZoneSuggestion.Builder builder =
+ new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX);
+ assertRoundTripParcelable(builder.build());
+
+ builder.setZoneId("Europe/London");
+ builder.setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID);
+ builder.setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
+ TelephonyTimeZoneSuggestion suggestion1 = builder.build();
+ assertRoundTripParcelable(suggestion1);
+
+ // DebugInfo should also be stored (but is not checked by equals()
+ String debugString = "This is debug info";
+ suggestion1.addDebugInfo(debugString);
+ TelephonyTimeZoneSuggestion suggestion1_2 = roundTripParcelable(suggestion1);
+ assertEquals(suggestion1, suggestion1_2);
+ assertTrue(suggestion1_2.getDebugInfo().contains(debugString));
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index b9a7e22..f83fb3f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -169,7 +169,7 @@
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
<permission name="android.permission.STATUS_BAR"/>
<permission name="android.permission.STOP_APP_SWITCHES"/>
- <permission name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"/>
+ <permission name="android.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
<permission name="android.permission.UPDATE_DEVICE_STATS"/>
<permission name="android.permission.UPDATE_LOCK"/>
diff --git a/packages/SystemUI/res/drawable/ic_device_unknown_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_device_unknown_gm2_24px.xml
new file mode 100644
index 0000000..24e0635
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_unknown_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12,2l-5.5,9h11L12,2zM12,5.84L13.93,9h-3.87L12,5.84zM17.5,13c-2.49,0 -4.5,2.01 -4.5,4.5s2.01,4.5 4.5,4.5 4.5,-2.01 4.5,-4.5 -2.01,-4.5 -4.5,-4.5zM17.5,20c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5zM3,21.5h8v-8L3,13.5v8zM5,15.5h4v4L5,19.5v-4z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_touch.xml b/packages/SystemUI/res/drawable/ic_touch.xml
new file mode 100644
index 0000000..4f6698d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_touch.xml
@@ -0,0 +1,26 @@
+<!--
+Copyright (C) 2020 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.
+-->
+<!-- maybe need android:fillType="evenOdd" -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,7.5V11.24C7.79,10.43 7,9.06 7,7.5C7,5.01 9.01,3 11.5,3C13.99,3 16,5.01 16,7.5C16,9.06 15.21,10.43 14,11.24V7.5C14,6.12 12.88,5 11.5,5C10.12,5 9,6.12 9,7.5ZM14.3,13.61L18.84,15.87C19.37,16.09 19.75,16.63 19.75,17.25C19.75,17.31 19.74,17.38 19.73,17.45L18.98,22.72C18.87,23.45 18.29,24 17.54,24H10.75C10.34,24 9.96,23.83 9.69,23.56L4.75,18.62L5.54,17.82C5.74,17.62 6.02,17.49 6.33,17.49C6.39,17.49 6.4411,17.4989 6.4922,17.5078C6.5178,17.5122 6.5433,17.5167 6.57,17.52L10,18.24V7.5C10,6.67 10.67,6 11.5,6C12.33,6 13,6.67 13,7.5V13.5H13.76C13.95,13.5 14.13,13.54 14.3,13.61Z"
+ />
+</vector>
diff --git a/packages/SystemUI/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml
new file mode 100644
index 0000000..df576d8
--- /dev/null
+++ b/packages/SystemUI/res/layout/screen_record_dialog.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:background="@drawable/rounded_bg_full">
+
+ <!-- Header -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:padding="@dimen/screenrecord_dialog_padding">
+ <ImageView
+ android:layout_width="@dimen/screenrecord_logo_size"
+ android:layout_height="@dimen/screenrecord_logo_size"
+ android:src="@drawable/ic_screenrecord"
+ android:tint="@color/GM2_red_500"
+ android:layout_marginBottom="@dimen/screenrecord_dialog_padding"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="@string/screenrecord_start_label"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/screenrecord_description"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:paddingTop="@dimen/screenrecord_dialog_padding"
+ android:paddingBottom="@dimen/screenrecord_dialog_padding"/>
+
+ <!-- Options -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <ImageView
+ android:layout_width="@dimen/screenrecord_logo_size"
+ android:layout_height="@dimen/screenrecord_logo_size"
+ android:src="@drawable/ic_mic_26dp"
+ android:tint="@color/GM2_grey_700"
+ android:layout_gravity="center"
+ android:layout_weight="0"
+ android:layout_marginRight="@dimen/screenrecord_dialog_padding"/>
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_weight="1">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical"
+ android:text="@string/screenrecord_audio_label"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/audio_type"
+ android:text="@string/screenrecord_mic_label"
+ android:textAppearance="?android:attr/textAppearanceSmall"/>
+ </LinearLayout>
+ <Switch
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_weight="0"
+ android:id="@+id/screenrecord_audio_switch"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <ImageView
+ android:layout_width="@dimen/screenrecord_logo_size"
+ android:layout_height="@dimen/screenrecord_logo_size"
+ android:src="@drawable/ic_touch"
+ android:tint="@color/GM2_grey_700"
+ android:layout_gravity="center"
+ android:layout_marginRight="@dimen/screenrecord_dialog_padding"/>
+ <Switch
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:id="@+id/screenrecord_taps_switch"
+ android:text="@string/screenrecord_taps_label"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+ </LinearLayout>
+ </LinearLayout>
+
+ <!-- hr -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@color/GM2_grey_300"/>
+
+ <!-- Buttons -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:padding="@dimen/screenrecord_dialog_padding">
+ <Button
+ android:id="@+id/button_cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:layout_gravity="start"
+ android:text="@string/cancel"
+ style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"/>
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"/>
+ <Button
+ android:id="@+id/button_start"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:layout_gravity="end"
+ android:text="@string/screenrecord_start"
+ style="@android:style/Widget.DeviceDefault.Button.Colored"/>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 5a1d1e2..c4fa4e5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1209,5 +1209,7 @@
<dimen name="controls_card_margin">2dp</dimen>
-
+ <!-- Screen Record -->
+ <dimen name="screenrecord_dialog_padding">18dp</dimen>
+ <dimen name="screenrecord_logo_size">24dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 07a926f..b85b51e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -217,15 +217,31 @@
your organization</string>
<!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
- <string name="screenrecord_name">Screen Recording</string>
+ <string name="screenrecord_name">Screen Recorder</string>
<!-- Description of the screen recording notification channel [CHAR LIMIT=NONE]-->
<string name="screenrecord_channel_description">Ongoing notification for a screen record session</string>
- <!-- Label for the button to begin screen recording [CHAR LIMIT=NONE]-->
- <string name="screenrecord_start_label">Start Recording</string>
- <!-- Label for the checkbox to enable microphone input during screen recording [CHAR LIMIT=NONE]-->
- <string name="screenrecord_mic_label">Record voiceover</string>
+ <!-- Title for the screen prompting the user to begin recording their screen [CHAR LIMIT=NONE]-->
+ <string name="screenrecord_start_label">Start Recording?</string>
+ <!-- Message reminding the user that sensitive information may be captured during a screen recording [CHAR_LIMIT=NONE]-->
+ <string name="screenrecord_description">While recording, Android System can capture any sensitive information that\u2019s visible on your screen or played on your device. This includes passwords, payment info, photos, messages, and audio.</string>
+ <!-- Label for a switch to enable recording audio [CHAR LIMIT=NONE]-->
+ <string name="screenrecord_audio_label">Record audio</string>
+ <!-- Label for the option to record audio from the device [CHAR LIMIT=NONE]-->
+ <string name="screenrecord_device_audio_label">Device audio</string>
+ <!-- Description of what audio may be captured from the device [CHAR LIMIT=NONE]-->
+ <string name="screenrecord_device_audio_description">Sound from your device, like music, calls, and ringtones</string>
+ <!-- Label for the option to enable microphone input during screen recording [CHAR LIMIT=NONE]-->
+ <string name="screenrecord_mic_label">Microphone</string>
+ <!-- Label for an option to record audio from both device and microphone [CHAR LIMIT=NONE]-->
+ <string name="screenrecord_device_audio_and_mic_label">Device audio and microphone</string>
+ <!-- Button to start a screen recording [CHAR LIMIT=50]-->
+ <string name="screenrecord_start">Start</string>
+ <!-- Notification text displayed when we are recording the screen [CHAR LIMIT=100]-->
+ <string name="screenrecord_ongoing_screen_only">Recording screen</string>
+ <!-- Notification text displayed when we are recording both the screen and audio [CHAR LIMIT=100]-->
+ <string name="screenrecord_ongoing_screen_and_audio">Recording screen and audio</string>
<!-- Label for the checkbox to enable showing location of touches during screen recording [CHAR LIMIT=NONE]-->
- <string name="screenrecord_taps_label">Show taps</string>
+ <string name="screenrecord_taps_label">Show touches on screen</string>
<!-- Label for notification that the user can tap to stop and save the screen recording [CHAR LIMIT=NONE] -->
<string name="screenrecord_stop_text">Tap to stop</string>
<!-- Label for notification action to stop and save the screen recording [CHAR LIMIT=35] -->
@@ -250,6 +266,8 @@
<string name="screenrecord_delete_error">Error deleting screen recording</string>
<!-- A toast message shown when the screen recording cannot be started due to insufficient permissions [CHAR LIMIT=NONE] -->
<string name="screenrecord_permission_error">Failed to get permissions</string>
+ <!-- A toast message shown when the screen recording cannot be started due to a generic error [CHAR LIMIT=NONE] -->
+ <string name="screenrecord_start_error">Error starting screen recording</string>
<!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
<string name="usb_preference_title">USB file transfer options</string>
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
index 093c99f..da52c6f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
@@ -108,10 +108,18 @@
DeviceTypes.TYPE_OUTLET to IconState(
R.drawable.ic_power_off_gm2_24px,
R.drawable.ic_power_gm2_24px
+ ),
+ DeviceTypes.TYPE_VACUUM to IconState(
+ R.drawable.ic_vacuum_gm2_24px,
+ R.drawable.ic_vacuum_gm2_24px
+ ),
+ DeviceTypes.TYPE_MOP to IconState(
+ R.drawable.ic_vacuum_gm2_24px,
+ R.drawable.ic_vacuum_gm2_24px
)
).withDefault {
IconState(
- R.drawable.ic_light_off_gm2_24px,
- R.drawable.ic_lightbulb_outline_gm2_24px
+ R.drawable.ic_device_unknown_gm2_24px,
+ R.drawable.ic_device_unknown_gm2_24px
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index b091ad8..626f298 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -16,7 +16,6 @@
package com.android.systemui.screenrecord;
-import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -26,16 +25,21 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
+import android.media.projection.IMediaProjection;
+import android.media.projection.IMediaProjectionManager;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.DisplayMetrics;
@@ -83,7 +87,6 @@
private static final int AUDIO_SAMPLE_RATE = 44100;
private final RecordingController mController;
- private MediaProjectionManager mMediaProjectionManager;
private MediaProjection mMediaProjection;
private Surface mInputSurface;
private VirtualDisplay mVirtualDisplay;
@@ -134,13 +137,30 @@
switch (action) {
case ACTION_START:
- int resultCode = intent.getIntExtra(EXTRA_RESULT_CODE, Activity.RESULT_CANCELED);
mUseAudio = intent.getBooleanExtra(EXTRA_USE_AUDIO, false);
mShowTaps = intent.getBooleanExtra(EXTRA_SHOW_TAPS, false);
- Intent data = intent.getParcelableExtra(EXTRA_DATA);
- if (data != null) {
- mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
+ try {
+ IBinder b = ServiceManager.getService(MEDIA_PROJECTION_SERVICE);
+ IMediaProjectionManager mediaService =
+ IMediaProjectionManager.Stub.asInterface(b);
+ IMediaProjection proj = mediaService.createProjection(getUserId(),
+ getPackageName(),
+ MediaProjectionManager.TYPE_SCREEN_CAPTURE, false);
+ IBinder projection = proj.asBinder();
+ if (projection == null) {
+ Log.e(TAG, "Projection was null");
+ Toast.makeText(this, R.string.screenrecord_start_error, Toast.LENGTH_LONG)
+ .show();
+ return Service.START_NOT_STICKY;
+ }
+ mMediaProjection = new MediaProjection(getApplicationContext(),
+ IMediaProjection.Stub.asInterface(projection));
startRecording();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ Toast.makeText(this, R.string.screenrecord_start_error, Toast.LENGTH_LONG)
+ .show();
+ return Service.START_NOT_STICKY;
}
break;
@@ -195,9 +215,6 @@
@Override
public void onCreate() {
super.onCreate();
-
- mMediaProjectionManager =
- (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
/**
@@ -269,6 +286,7 @@
}
private void createRecordingNotification() {
+ Resources res = getResources();
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
getString(R.string.screenrecord_name),
@@ -281,11 +299,15 @@
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- getResources().getString(R.string.screenrecord_name));
+ res.getString(R.string.screenrecord_name));
+
+ String notificationTitle = mUseAudio
+ ? res.getString(R.string.screenrecord_ongoing_screen_and_audio)
+ : res.getString(R.string.screenrecord_ongoing_screen_only);
mRecordingNotificationBuilder = new Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_screenrecord)
- .setContentTitle(getResources().getString(R.string.screenrecord_name))
+ .setContentTitle(notificationTitle)
.setContentText(getResources().getString(R.string.screenrecord_stop_text))
.setUsesChronometer(true)
.setColorized(true)
@@ -332,8 +354,7 @@
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_screenrecord)
- .setContentTitle(getResources().getString(R.string.screenrecord_name))
- .setContentText(getResources().getString(R.string.screenrecord_save_message))
+ .setContentTitle(getResources().getString(R.string.screenrecord_save_message))
.setContentIntent(PendingIntent.getActivity(
this,
REQUEST_CODE,
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
index 8324986..566f12b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
@@ -16,15 +16,14 @@
package com.android.systemui.screenrecord;
-import android.Manifest;
import android.app.Activity;
import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
-import android.widget.Toast;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.Switch;
import com.android.systemui.R;
@@ -34,15 +33,11 @@
* Activity to select screen recording options
*/
public class ScreenRecordDialog extends Activity {
- private static final int REQUEST_CODE_VIDEO_ONLY = 200;
- private static final int REQUEST_CODE_VIDEO_TAPS = 201;
- private static final int REQUEST_CODE_PERMISSIONS = 299;
- private static final int REQUEST_CODE_VIDEO_AUDIO = 300;
- private static final int REQUEST_CODE_VIDEO_AUDIO_TAPS = 301;
- private static final int REQUEST_CODE_PERMISSIONS_AUDIO = 399;
private static final long DELAY_MS = 3000;
private final RecordingController mController;
+ private Switch mAudioSwitch;
+ private Switch mTapsSwitch;
@Inject
public ScreenRecordDialog(RecordingController controller) {
@@ -52,81 +47,42 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- requestScreenCapture();
+
+ Window window = getWindow();
+ // Inflate the decor view, so the attributes below are not overwritten by the theme.
+ window.getDecorView();
+ window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ window.setGravity(Gravity.TOP);
+
+ setContentView(R.layout.screen_record_dialog);
+
+ Button cancelBtn = findViewById(R.id.button_cancel);
+ cancelBtn.setOnClickListener(v -> {
+ finish();
+ });
+
+ Button startBtn = findViewById(R.id.button_start);
+ startBtn.setOnClickListener(v -> {
+ requestScreenCapture();
+ finish();
+ });
+
+ mAudioSwitch = findViewById(R.id.screenrecord_audio_switch);
+ mTapsSwitch = findViewById(R.id.screenrecord_taps_switch);
}
private void requestScreenCapture() {
- MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(
- Context.MEDIA_PROJECTION_SERVICE);
- Intent permissionIntent = mediaProjectionManager.createScreenCaptureIntent();
-
- // TODO get saved settings
- boolean useAudio = false;
- boolean showTaps = false;
- if (useAudio) {
- startActivityForResult(permissionIntent,
- showTaps ? REQUEST_CODE_VIDEO_AUDIO_TAPS : REQUEST_CODE_VIDEO_AUDIO);
- } else {
- startActivityForResult(permissionIntent,
- showTaps ? REQUEST_CODE_VIDEO_TAPS : REQUEST_CODE_VIDEO_ONLY);
- }
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- boolean showTaps = (requestCode == REQUEST_CODE_VIDEO_TAPS
- || requestCode == REQUEST_CODE_VIDEO_AUDIO_TAPS);
- boolean useAudio = (requestCode == REQUEST_CODE_VIDEO_AUDIO
- || requestCode == REQUEST_CODE_VIDEO_AUDIO_TAPS);
- switch (requestCode) {
- case REQUEST_CODE_VIDEO_TAPS:
- case REQUEST_CODE_VIDEO_AUDIO_TAPS:
- case REQUEST_CODE_VIDEO_ONLY:
- case REQUEST_CODE_VIDEO_AUDIO:
- if (resultCode == RESULT_OK) {
- PendingIntent startIntent = PendingIntent.getForegroundService(
- this, RecordingService.REQUEST_CODE, RecordingService.getStartIntent(
- ScreenRecordDialog.this, resultCode, data, useAudio,
- showTaps),
- PendingIntent.FLAG_UPDATE_CURRENT
- );
- PendingIntent stopIntent = PendingIntent.getService(
- this, RecordingService.REQUEST_CODE,
- RecordingService.getStopIntent(this),
- PendingIntent.FLAG_UPDATE_CURRENT);
- mController.startCountdown(DELAY_MS, startIntent, stopIntent);
- } else {
- Toast.makeText(this,
- getResources().getString(R.string.screenrecord_permission_error),
- Toast.LENGTH_SHORT).show();
- }
- finish();
- break;
- case REQUEST_CODE_PERMISSIONS:
- int permission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
- if (permission != PackageManager.PERMISSION_GRANTED) {
- Toast.makeText(this,
- getResources().getString(R.string.screenrecord_permission_error),
- Toast.LENGTH_SHORT).show();
- finish();
- } else {
- requestScreenCapture();
- }
- break;
- case REQUEST_CODE_PERMISSIONS_AUDIO:
- int videoPermission = checkSelfPermission(
- Manifest.permission.WRITE_EXTERNAL_STORAGE);
- int audioPermission = checkSelfPermission(Manifest.permission.RECORD_AUDIO);
- if (videoPermission != PackageManager.PERMISSION_GRANTED
- || audioPermission != PackageManager.PERMISSION_GRANTED) {
- Toast.makeText(this,
- getResources().getString(R.string.screenrecord_permission_error),
- Toast.LENGTH_SHORT).show();
- finish();
- } else {
- requestScreenCapture();
- }
- break;
- }
+ boolean useAudio = mAudioSwitch.isChecked();
+ boolean showTaps = mTapsSwitch.isChecked();
+ PendingIntent startIntent = PendingIntent.getForegroundService(this,
+ RecordingService.REQUEST_CODE,
+ RecordingService.getStartIntent(
+ ScreenRecordDialog.this, RESULT_OK, null, useAudio, showTaps),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent stopIntent = PendingIntent.getService(this,
+ RecordingService.REQUEST_CODE,
+ RecordingService.getStopIntent(this),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ mController.startCountdown(DELAY_MS, startIntent, stopIntent);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b52289e..f071135 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2681,18 +2681,24 @@
@Override
public void enqueueTextToast(String pkg, IBinder token, CharSequence text, int duration,
int displayId, @Nullable ITransientNotificationCallback callback) {
- enqueueToast(pkg, token, text, null, duration, displayId, callback);
+ enqueueToast(pkg, token, text, null, duration, displayId, callback, false);
}
@Override
public void enqueueToast(String pkg, IBinder token, ITransientNotification callback,
int duration, int displayId) {
- enqueueToast(pkg, token, null, callback, duration, displayId, null);
+ enqueueToast(pkg, token, null, callback, duration, displayId, null, true);
+ }
+
+ @Override
+ public void enqueueTextOrCustomToast(String pkg, IBinder token,
+ ITransientNotification callback, int duration, int displayId, boolean isCustom) {
+ enqueueToast(pkg, token, null, callback, duration, displayId, null, isCustom);
}
private void enqueueToast(String pkg, IBinder token, @Nullable CharSequence text,
@Nullable ITransientNotification callback, int duration, int displayId,
- @Nullable ITransientNotificationCallback textCallback) {
+ @Nullable ITransientNotificationCallback textCallback, boolean isCustom) {
if (DBG) {
Slog.i(TAG, "enqueueToast pkg=" + pkg + " token=" + token
+ " duration=" + duration + " displayId=" + displayId);
@@ -2730,7 +2736,7 @@
return;
}
- if (callback != null && !appIsForeground && !isSystemToast) {
+ if (callback != null && !appIsForeground && !isSystemToast && isCustom) {
boolean block;
long id = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index 639cc70..90fc59a 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -38,6 +38,8 @@
import android.util.LruCache;
import android.util.Slog;
+import libcore.util.EmptyArray;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
@@ -301,7 +303,7 @@
for (String person: second) {
people.add(person);
}
- return (String[]) people.toArray();
+ return people.toArray(EmptyArray.STRING);
}
@Nullable
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d663b0b..0cf8b42 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -129,6 +129,7 @@
import com.android.server.security.VerityUtils;
import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -212,7 +213,8 @@
private static final String ATTR_SIGNATURE = "signature";
private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
- private static final int[] EMPTY_CHILD_SESSION_ARRAY = {};
+ private static final int[] EMPTY_CHILD_SESSION_ARRAY = EmptyArray.INT;
+ private static final FileInfo[] EMPTY_FILE_INFO_ARRAY = {};
private static final String SYSTEM_DATA_LOADER_PACKAGE = "android";
@@ -375,8 +377,6 @@
// TODO(b/146080380): merge file list with Callback installation.
private IncrementalFileStorages mIncrementalFileStorages;
- private static final String[] EMPTY_STRING_ARRAY = new String[]{};
-
private static final FileFilter sAddedApkFilter = new FileFilter() {
@Override
public boolean accept(File file) {
@@ -731,7 +731,7 @@
if (!isDataLoaderInstallation()) {
String[] result = stageDir.list();
if (result == null) {
- result = EMPTY_STRING_ARRAY;
+ result = EmptyArray.STRING;
}
return result;
}
@@ -3120,7 +3120,8 @@
}
if (grantedRuntimePermissions.size() > 0) {
- params.grantedRuntimePermissions = (String[]) grantedRuntimePermissions.toArray();
+ params.grantedRuntimePermissions =
+ grantedRuntimePermissions.toArray(EmptyArray.STRING);
}
if (whitelistedRestrictedPermissions.size() > 0) {
@@ -3139,7 +3140,7 @@
FileInfo[] fileInfosArray = null;
if (!files.isEmpty()) {
- fileInfosArray = (FileInfo[]) files.toArray();
+ fileInfosArray = files.toArray(EMPTY_FILE_INFO_ARRAY);
}
InstallSource installSource = InstallSource.create(installInitiatingPackageName,
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 0bb0f94..ed6424c 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -21,7 +21,7 @@
import android.app.timedetector.ITimeDetectorService;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -94,11 +94,11 @@
}
@Override
- public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSignal) {
- enforceSuggestPhoneTimePermission();
+ public void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSignal) {
+ enforceSuggestTelephonyTimePermission();
Objects.requireNonNull(timeSignal);
- mHandler.post(() -> mTimeDetectorStrategy.suggestPhoneTime(timeSignal));
+ mHandler.post(() -> mTimeDetectorStrategy.suggestTelephonyTime(timeSignal));
}
@Override
@@ -131,10 +131,10 @@
mTimeDetectorStrategy.dump(pw, args);
}
- private void enforceSuggestPhoneTimePermission() {
+ private void enforceSuggestTelephonyTimePermission() {
mContext.enforceCallingPermission(
- android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE,
- "suggest phone time and time zone");
+ android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE,
+ "suggest telephony time and time zone");
}
private void enforceSuggestManualTimePermission() {
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index a7c3b4d..a5fba4e 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
import android.os.TimestampedValue;
import java.io.PrintWriter;
@@ -78,7 +78,7 @@
void initialize(@NonNull Callback callback);
/** Process the suggested time from telephony sources. */
- void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion);
+ void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion);
/** Process the suggested manually entered time. */
void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion);
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 19435ee..8c54fa9 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -22,7 +22,7 @@
import android.app.AlarmManager;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
import android.os.TimestampedValue;
import android.util.LocalLog;
import android.util.Slog;
@@ -38,9 +38,9 @@
import java.lang.annotation.RetentionPolicy;
/**
- * An implementation of {@link TimeDetectorStrategy} that passes phone and manual suggestions to
- * {@link AlarmManager}. When there are multiple phone sources, the one with the lowest ID is used
- * unless the data becomes too stale.
+ * An implementation of {@link TimeDetectorStrategy} that passes telephony and manual suggestions to
+ * {@link AlarmManager}. When there are multiple telephony sources, the one with the lowest ID is
+ * used unless the data becomes too stale.
*
* <p>Most public methods are marked synchronized to ensure thread safety around internal state.
*/
@@ -50,23 +50,26 @@
private static final String LOG_TAG = "SimpleTimeDetectorStrategy";
/** A score value used to indicate "no score", either due to validation failure or age. */
- private static final int PHONE_INVALID_SCORE = -1;
- /** The number of buckets phone suggestions can be put in by age. */
- private static final int PHONE_BUCKET_COUNT = 24;
+ private static final int TELEPHONY_INVALID_SCORE = -1;
+ /** The number of buckets telephony suggestions can be put in by age. */
+ private static final int TELEPHONY_BUCKET_COUNT = 24;
/** Each bucket is this size. All buckets are equally sized. */
@VisibleForTesting
- static final int PHONE_BUCKET_SIZE_MILLIS = 60 * 60 * 1000;
- /** Phone and network suggestions older than this value are considered too old to be used. */
+ static final int TELEPHONY_BUCKET_SIZE_MILLIS = 60 * 60 * 1000;
+ /**
+ * Telephony and network suggestions older than this value are considered too old to be used.
+ */
@VisibleForTesting
- static final long MAX_UTC_TIME_AGE_MILLIS = PHONE_BUCKET_COUNT * PHONE_BUCKET_SIZE_MILLIS;
+ static final long MAX_UTC_TIME_AGE_MILLIS =
+ TELEPHONY_BUCKET_COUNT * TELEPHONY_BUCKET_SIZE_MILLIS;
- @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL, ORIGIN_NETWORK })
+ @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
@Retention(RetentionPolicy.SOURCE)
public @interface Origin {}
/** Used when a time value originated from a telephony signal. */
@Origin
- private static final int ORIGIN_PHONE = 1;
+ private static final int ORIGIN_TELEPHONY = 1;
/** Used when a time value originated from a user / manual settings. */
@Origin
@@ -83,7 +86,9 @@
*/
private static final long SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS = 2 * 1000;
- /** The number of previous phone suggestions to keep for each ID (for use during debugging). */
+ /**
+ * The number of previous telephony suggestions to keep for each ID (for use during debugging).
+ */
private static final int KEEP_SUGGESTION_HISTORY_SIZE = 30;
// A log for changes made to the system clock and why.
@@ -106,7 +111,7 @@
* stable.
*/
@GuardedBy("this")
- private final ArrayMapWithHistory<Integer, PhoneTimeSuggestion> mSuggestionBySlotIndex =
+ private final ArrayMapWithHistory<Integer, TelephonyTimeSuggestion> mSuggestionBySlotIndex =
new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
@GuardedBy("this")
@@ -144,7 +149,7 @@
}
@Override
- public synchronized void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
+ public synchronized void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion) {
// Empty time suggestion means that telephony network connectivity has been lost.
// The passage of time is relentless, and we don't expect our users to use a time machine,
// so we can continue relying on previous suggestions when we lose connectivity. This is
@@ -157,13 +162,13 @@
// Perform validation / input filtering and record the validated suggestion against the
// slotIndex.
- if (!validateAndStorePhoneSuggestion(timeSuggestion)) {
+ if (!validateAndStoreTelephonySuggestion(timeSuggestion)) {
return;
}
// Now perform auto time detection. The new suggestion may be used to modify the system
// clock.
- String reason = "New phone time suggested. timeSuggestion=" + timeSuggestion;
+ String reason = "New telephony time suggested. timeSuggestion=" + timeSuggestion;
doAutoTimeDetection(reason);
}
@@ -201,7 +206,7 @@
mTimeChangesLog.dump(ipw);
ipw.decreaseIndent(); // level 2
- ipw.println("Phone suggestion history:");
+ ipw.println("Telephony suggestion history:");
ipw.increaseIndent(); // level 2
mSuggestionBySlotIndex.dump(ipw);
ipw.decreaseIndent(); // level 2
@@ -216,7 +221,8 @@
}
@GuardedBy("this")
- private boolean validateAndStorePhoneSuggestion(@NonNull PhoneTimeSuggestion suggestion) {
+ private boolean validateAndStoreTelephonySuggestion(
+ @NonNull TelephonyTimeSuggestion suggestion) {
TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
if (!validateSuggestionTime(newUtcTime, suggestion)) {
// There's probably nothing useful we can do: elsewhere we assume that reference
@@ -225,7 +231,7 @@
}
int slotIndex = suggestion.getSlotIndex();
- PhoneTimeSuggestion previousSuggestion = mSuggestionBySlotIndex.get(slotIndex);
+ TelephonyTimeSuggestion previousSuggestion = mSuggestionBySlotIndex.get(slotIndex);
if (previousSuggestion != null) {
// We can log / discard suggestions with obvious issues with the reference time clock.
if (previousSuggestion.getUtcTime() == null
@@ -241,7 +247,7 @@
newUtcTime, previousSuggestion.getUtcTime());
if (referenceTimeDifference < 0) {
// The reference time is before the previously received suggestion. Ignore it.
- Slog.w(LOG_TAG, "Out of order phone suggestion received."
+ Slog.w(LOG_TAG, "Out of order telephony suggestion received."
+ " referenceTimeDifference=" + referenceTimeDifference
+ " previousSuggestion=" + previousSuggestion
+ " suggestion=" + suggestion);
@@ -282,18 +288,18 @@
// Android devices currently prioritize any telephony over network signals. There are
// carrier compliance tests that would need to be changed before we could ignore NITZ or
- // prefer NTP generally. This check is cheap on devices without phone hardware.
- PhoneTimeSuggestion bestPhoneSuggestion = findBestPhoneSuggestion();
- if (bestPhoneSuggestion != null) {
- final TimestampedValue<Long> newUtcTime = bestPhoneSuggestion.getUtcTime();
- String cause = "Found good phone suggestion."
- + ", bestPhoneSuggestion=" + bestPhoneSuggestion
+ // prefer NTP generally. This check is cheap on devices without telephony hardware.
+ TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion();
+ if (bestTelephonySuggestion != null) {
+ final TimestampedValue<Long> newUtcTime = bestTelephonySuggestion.getUtcTime();
+ String cause = "Found good telephony suggestion."
+ + ", bestTelephonySuggestion=" + bestTelephonySuggestion
+ ", detectionReason=" + detectionReason;
- setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, cause);
+ setSystemClockIfRequired(ORIGIN_TELEPHONY, newUtcTime, cause);
return;
}
- // There is no good phone suggestion, try network.
+ // There is no good telephony suggestion, try network.
NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
if (networkSuggestion != null) {
final TimestampedValue<Long> newUtcTime = networkSuggestion.getUtcTime();
@@ -305,18 +311,18 @@
}
if (DBG) {
- Slog.d(LOG_TAG, "Could not determine time: No best phone or network suggestion."
+ Slog.d(LOG_TAG, "Could not determine time: No best telephony or network suggestion."
+ " detectionReason=" + detectionReason);
}
}
@GuardedBy("this")
@Nullable
- private PhoneTimeSuggestion findBestPhoneSuggestion() {
+ private TelephonyTimeSuggestion findBestTelephonySuggestion() {
long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
- // Phone time suggestions are assumed to be derived from NITZ or NITZ-like signals. These
- // have a number of limitations:
+ // Telephony time suggestions are assumed to be derived from NITZ or NITZ-like signals.
+ // These have a number of limitations:
// 1) No guarantee of accuracy ("accuracy of the time information is in the order of
// minutes") [1]
// 2) No guarantee of regular signals ("dependent on the handset crossing radio network
@@ -335,8 +341,8 @@
// For simplicity, we try to value recency, then consistency of slotIndex.
//
// The heuristic works as follows:
- // Recency: The most recent suggestion from each phone is scored. The score is based on a
- // discrete age bucket, i.e. so signals received around the same time will be in the same
+ // Recency: The most recent suggestion from each slotIndex is scored. The score is based on
+ // a discrete age bucket, i.e. so signals received around the same time will be in the same
// bucket, thus applying a loose reference time ordering. The suggestion with the highest
// score is used.
// Consistency: If there a multiple suggestions with the same score, the suggestion with the
@@ -345,11 +351,11 @@
// In the trivial case with a single ID this will just mean that the latest received
// suggestion is used.
- PhoneTimeSuggestion bestSuggestion = null;
- int bestScore = PHONE_INVALID_SCORE;
+ TelephonyTimeSuggestion bestSuggestion = null;
+ int bestScore = TELEPHONY_INVALID_SCORE;
for (int i = 0; i < mSuggestionBySlotIndex.size(); i++) {
Integer slotIndex = mSuggestionBySlotIndex.keyAt(i);
- PhoneTimeSuggestion candidateSuggestion = mSuggestionBySlotIndex.valueAt(i);
+ TelephonyTimeSuggestion candidateSuggestion = mSuggestionBySlotIndex.valueAt(i);
if (candidateSuggestion == null) {
// Unexpected - null suggestions should never be stored.
Slog.w(LOG_TAG, "Latest suggestion unexpectedly null for slotIndex."
@@ -362,8 +368,9 @@
continue;
}
- int candidateScore = scorePhoneSuggestion(elapsedRealtimeMillis, candidateSuggestion);
- if (candidateScore == PHONE_INVALID_SCORE) {
+ int candidateScore =
+ scoreTelephonySuggestion(elapsedRealtimeMillis, candidateSuggestion);
+ if (candidateScore == TELEPHONY_INVALID_SCORE) {
// Expected: This means the suggestion is obviously invalid or just too old.
continue;
}
@@ -384,8 +391,8 @@
return bestSuggestion;
}
- private static int scorePhoneSuggestion(
- long elapsedRealtimeMillis, @NonNull PhoneTimeSuggestion timeSuggestion) {
+ private static int scoreTelephonySuggestion(
+ long elapsedRealtimeMillis, @NonNull TelephonyTimeSuggestion timeSuggestion) {
// Validate first.
TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime();
@@ -393,21 +400,21 @@
Slog.w(LOG_TAG, "Existing suggestion found to be invalid "
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ ", timeSuggestion=" + timeSuggestion);
- return PHONE_INVALID_SCORE;
+ return TELEPHONY_INVALID_SCORE;
}
// The score is based on the age since receipt. Suggestions are bucketed so two
// suggestions in the same bucket from different slotIndexs are scored the same.
long ageMillis = elapsedRealtimeMillis - utcTime.getReferenceTimeMillis();
- // Turn the age into a discrete value: 0 <= bucketIndex < PHONE_BUCKET_COUNT.
- int bucketIndex = (int) (ageMillis / PHONE_BUCKET_SIZE_MILLIS);
- if (bucketIndex >= PHONE_BUCKET_COUNT) {
- return PHONE_INVALID_SCORE;
+ // Turn the age into a discrete value: 0 <= bucketIndex < TELEPHONY_BUCKET_COUNT.
+ int bucketIndex = (int) (ageMillis / TELEPHONY_BUCKET_SIZE_MILLIS);
+ if (bucketIndex >= TELEPHONY_BUCKET_COUNT) {
+ return TELEPHONY_INVALID_SCORE;
}
// We want the lowest bucket index to have the highest score. 0 > score >= BUCKET_COUNT.
- return PHONE_BUCKET_COUNT - bucketIndex;
+ return TELEPHONY_BUCKET_COUNT - bucketIndex;
}
/** Returns the latest, valid, network suggestion. Returns {@code null} if there isn't one. */
@@ -537,13 +544,13 @@
}
/**
- * Returns the current best phone suggestion. Not intended for general use: it is used during
- * tests to check strategy behavior.
+ * Returns the current best telephony suggestion. Not intended for general use: it is used
+ * during tests to check strategy behavior.
*/
@VisibleForTesting
@Nullable
- public synchronized PhoneTimeSuggestion findBestPhoneSuggestionForTests() {
- return findBestPhoneSuggestion();
+ public synchronized TelephonyTimeSuggestion findBestTelephonySuggestionForTests() {
+ return findBestTelephonySuggestion();
}
/**
@@ -561,7 +568,7 @@
*/
@VisibleForTesting
@Nullable
- public synchronized PhoneTimeSuggestion getLatestPhoneSuggestion(int slotIndex) {
+ public synchronized TelephonyTimeSuggestion getLatestTelephonySuggestion(int slotIndex) {
return mSuggestionBySlotIndex.get(slotIndex);
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index 381ee10..57b6ec9 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.app.timezonedetector.ITimeZoneDetectorService;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -101,11 +101,11 @@
}
@Override
- public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) {
- enforceSuggestPhoneTimeZonePermission();
+ public void suggestTelephonyTimeZone(@NonNull TelephonyTimeZoneSuggestion timeZoneSuggestion) {
+ enforceSuggestTelephonyTimeZonePermission();
Objects.requireNonNull(timeZoneSuggestion);
- mHandler.post(() -> mTimeZoneDetectorStrategy.suggestPhoneTimeZone(timeZoneSuggestion));
+ mHandler.post(() -> mTimeZoneDetectorStrategy.suggestTelephonyTimeZone(timeZoneSuggestion));
}
@Override
@@ -122,10 +122,10 @@
mHandler.post(mTimeZoneDetectorStrategy::handleAutoTimeZoneDetectionChanged);
}
- private void enforceSuggestPhoneTimeZonePermission() {
+ private void enforceSuggestTelephonyTimeZonePermission() {
mContext.enforceCallingPermission(
- android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE,
- "suggest phone time and time zone");
+ android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE,
+ "suggest telephony time and time zone");
}
private void enforceSuggestManualTimeZonePermission() {
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index 1d439e9..0eb27cc 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -17,7 +17,7 @@
import android.annotation.NonNull;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import java.io.PrintWriter;
@@ -38,13 +38,13 @@
/**
* Suggests a time zone for the device, or withdraws a previous suggestion if
- * {@link PhoneTimeZoneSuggestion#getZoneId()} is {@code null}. The suggestion is scoped to a
- * specific {@link PhoneTimeZoneSuggestion#getSlotIndex() phone}.
- * See {@link PhoneTimeZoneSuggestion} for an explanation of the metadata associated with a
+ * {@link TelephonyTimeZoneSuggestion#getZoneId()} is {@code null}. The suggestion is scoped to
+ * a specific {@link TelephonyTimeZoneSuggestion#getSlotIndex() slotIndex}.
+ * See {@link TelephonyTimeZoneSuggestion} for an explanation of the metadata associated with a
* suggestion. The strategy uses suggestions to decide whether to modify the device's time zone
* setting and what to set it to.
*/
- void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion suggestion);
+ void suggestTelephonyTimeZone(@NonNull TelephonyTimeZoneSuggestion suggestion);
/**
* Called when there has been a change to the automatic time zone detection setting.
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index f85f9fe..652dbe15 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -15,17 +15,17 @@
*/
package com.android.server.timezonedetector;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.content.Context;
import android.util.LocalLog;
import android.util.Slog;
@@ -44,11 +44,11 @@
* suggestions. Suggestions are acted on or ignored as needed, dependent on the current "auto time
* zone detection" setting.
*
- * <p>For automatic detection it keeps track of the most recent suggestion from each phone it uses
- * the best suggestion based on a scoring algorithm. If several phones provide the same score then
- * the phone with the lowest numeric ID "wins". If the situation changes and it is no longer
- * possible to be confident about the time zone, phones must submit an empty suggestion in order to
- * "withdraw" their previous suggestion.
+ * <p>For automatic detection, it keeps track of the most recent telephony suggestion from each
+ * slotIndex and it uses the best suggestion based on a scoring algorithm. If several slotIndexes
+ * provide the same score then the slotIndex with the lowest numeric value "wins". If the situation
+ * changes and it is no longer possible to be confident about the time zone, slotIndexes must have
+ * an empty suggestion submitted in order to "withdraw" their previous suggestion.
*
* <p>Most public methods are marked synchronized to ensure thread safety around internal state.
*/
@@ -91,28 +91,28 @@
private static final String LOG_TAG = "TimeZoneDetectorStrategy";
private static final boolean DBG = false;
- @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL })
+ @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL })
@Retention(RetentionPolicy.SOURCE)
public @interface Origin {}
/** Used when a time value originated from a telephony signal. */
@Origin
- private static final int ORIGIN_PHONE = 1;
+ private static final int ORIGIN_TELEPHONY = 1;
/** Used when a time value originated from a user / manual settings. */
@Origin
private static final int ORIGIN_MANUAL = 2;
/**
- * The abstract score for an empty or invalid phone suggestion.
+ * The abstract score for an empty or invalid telephony suggestion.
*
- * Used to score phone suggestions where there is no zone.
+ * Used to score telephony suggestions where there is no zone.
*/
@VisibleForTesting
- public static final int PHONE_SCORE_NONE = 0;
+ public static final int TELEPHONY_SCORE_NONE = 0;
/**
- * The abstract score for a low quality phone suggestion.
+ * The abstract score for a low quality telephony suggestion.
*
* Used to score suggestions where:
* The suggested zone ID is one of several possibilities, and the possibilities have different
@@ -121,10 +121,10 @@
* You would have to be quite desperate to want to use this choice.
*/
@VisibleForTesting
- public static final int PHONE_SCORE_LOW = 1;
+ public static final int TELEPHONY_SCORE_LOW = 1;
/**
- * The abstract score for a medium quality phone suggestion.
+ * The abstract score for a medium quality telephony suggestion.
*
* Used for:
* The suggested zone ID is one of several possibilities but at least the possibilities have the
@@ -132,36 +132,38 @@
* switch to DST at the wrong time and (for example) their calendar events.
*/
@VisibleForTesting
- public static final int PHONE_SCORE_MEDIUM = 2;
+ public static final int TELEPHONY_SCORE_MEDIUM = 2;
/**
- * The abstract score for a high quality phone suggestion.
+ * The abstract score for a high quality telephony suggestion.
*
* Used for:
* The suggestion was for one zone ID and the answer was unambiguous and likely correct given
* the info available.
*/
@VisibleForTesting
- public static final int PHONE_SCORE_HIGH = 3;
+ public static final int TELEPHONY_SCORE_HIGH = 3;
/**
- * The abstract score for a highest quality phone suggestion.
+ * The abstract score for a highest quality telephony suggestion.
*
* Used for:
* Suggestions that must "win" because they constitute test or emulator zone ID.
*/
@VisibleForTesting
- public static final int PHONE_SCORE_HIGHEST = 4;
+ public static final int TELEPHONY_SCORE_HIGHEST = 4;
/**
- * The threshold at which phone suggestions are good enough to use to set the device's time
+ * The threshold at which telephony suggestions are good enough to use to set the device's time
* zone.
*/
@VisibleForTesting
- public static final int PHONE_SCORE_USAGE_THRESHOLD = PHONE_SCORE_MEDIUM;
+ public static final int TELEPHONY_SCORE_USAGE_THRESHOLD = TELEPHONY_SCORE_MEDIUM;
- /** The number of previous phone suggestions to keep for each ID (for use during debugging). */
- private static final int KEEP_PHONE_SUGGESTION_HISTORY_SIZE = 30;
+ /**
+ * The number of previous telephony suggestions to keep for each ID (for use during debugging).
+ */
+ private static final int KEEP_TELEPHONY_SUGGESTION_HISTORY_SIZE = 30;
@NonNull
private final Callback mCallback;
@@ -174,13 +176,14 @@
private final LocalLog mTimeZoneChangesLog = new LocalLog(30, false /* useLocalTimestamps */);
/**
- * A mapping from slotIndex to a phone time zone suggestion. We typically expect one or two
- * mappings: devices will have a small number of telephony devices and slotIndexs are assumed to
- * be stable.
+ * A mapping from slotIndex to a telephony time zone suggestion. We typically expect one or two
+ * mappings: devices will have a small number of telephony devices and slotIndexes are assumed
+ * to be stable.
*/
@GuardedBy("this")
- private ArrayMapWithHistory<Integer, QualifiedPhoneTimeZoneSuggestion> mSuggestionBySlotIndex =
- new ArrayMapWithHistory<>(KEEP_PHONE_SUGGESTION_HISTORY_SIZE);
+ private ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion>
+ mSuggestionBySlotIndex =
+ new ArrayMapWithHistory<>(KEEP_TELEPHONY_SUGGESTION_HISTORY_SIZE);
/**
* Creates a new instance of {@link TimeZoneDetectorStrategyImpl}.
@@ -205,42 +208,43 @@
}
@Override
- public synchronized void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion suggestion) {
+ public synchronized void suggestTelephonyTimeZone(
+ @NonNull TelephonyTimeZoneSuggestion suggestion) {
if (DBG) {
- Slog.d(LOG_TAG, "Phone suggestion received. newSuggestion=" + suggestion);
+ Slog.d(LOG_TAG, "Telephony suggestion received. newSuggestion=" + suggestion);
}
Objects.requireNonNull(suggestion);
// Score the suggestion.
- int score = scorePhoneSuggestion(suggestion);
- QualifiedPhoneTimeZoneSuggestion scoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(suggestion, score);
+ int score = scoreTelephonySuggestion(suggestion);
+ QualifiedTelephonyTimeZoneSuggestion scoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(suggestion, score);
// Store the suggestion against the correct slotIndex.
mSuggestionBySlotIndex.put(suggestion.getSlotIndex(), scoredSuggestion);
// Now perform auto time zone detection. The new suggestion may be used to modify the time
// zone setting.
- String reason = "New phone time suggested. suggestion=" + suggestion;
+ String reason = "New telephony time suggested. suggestion=" + suggestion;
doAutoTimeZoneDetection(reason);
}
- private static int scorePhoneSuggestion(@NonNull PhoneTimeZoneSuggestion suggestion) {
+ private static int scoreTelephonySuggestion(@NonNull TelephonyTimeZoneSuggestion suggestion) {
int score;
if (suggestion.getZoneId() == null) {
- score = PHONE_SCORE_NONE;
+ score = TELEPHONY_SCORE_NONE;
} else if (suggestion.getMatchType() == MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY
|| suggestion.getMatchType() == MATCH_TYPE_EMULATOR_ZONE_ID) {
// Handle emulator / test cases : These suggestions should always just be used.
- score = PHONE_SCORE_HIGHEST;
+ score = TELEPHONY_SCORE_HIGHEST;
} else if (suggestion.getQuality() == QUALITY_SINGLE_ZONE) {
- score = PHONE_SCORE_HIGH;
+ score = TELEPHONY_SCORE_HIGH;
} else if (suggestion.getQuality() == QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET) {
// The suggestion may be wrong, but at least the offset should be correct.
- score = PHONE_SCORE_MEDIUM;
+ score = TELEPHONY_SCORE_MEDIUM;
} else if (suggestion.getQuality() == QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS) {
// The suggestion has a good chance of being wrong.
- score = PHONE_SCORE_LOW;
+ score = TELEPHONY_SCORE_LOW;
} else {
throw new AssertionError();
}
@@ -248,9 +252,9 @@
}
/**
- * Finds the best available time zone suggestion from all phones. If it is high-enough quality
- * and automatic time zone detection is enabled then it will be set on the device. The outcome
- * can be that this strategy becomes / remains un-opinionated and nothing is set.
+ * Finds the best available time zone suggestion from all slotIndexes. If it is high-enough
+ * quality and automatic time zone detection is enabled then it will be set on the device. The
+ * outcome can be that this strategy becomes / remains un-opinionated and nothing is set.
*/
@GuardedBy("this")
private void doAutoTimeZoneDetection(@NonNull String detectionReason) {
@@ -259,35 +263,37 @@
return;
}
- QualifiedPhoneTimeZoneSuggestion bestPhoneSuggestion = findBestPhoneSuggestion();
+ QualifiedTelephonyTimeZoneSuggestion bestTelephonySuggestion =
+ findBestTelephonySuggestion();
// Work out what to do with the best suggestion.
- if (bestPhoneSuggestion == null) {
- // There is no phone suggestion available at all. Become un-opinionated.
+ if (bestTelephonySuggestion == null) {
+ // There is no telephony suggestion available at all. Become un-opinionated.
if (DBG) {
- Slog.d(LOG_TAG, "Could not determine time zone: No best phone suggestion."
+ Slog.d(LOG_TAG, "Could not determine time zone: No best telephony suggestion."
+ " detectionReason=" + detectionReason);
}
return;
}
// Special case handling for uninitialized devices. This should only happen once.
- String newZoneId = bestPhoneSuggestion.suggestion.getZoneId();
+ String newZoneId = bestTelephonySuggestion.suggestion.getZoneId();
if (newZoneId != null && !mCallback.isDeviceTimeZoneInitialized()) {
String cause = "Device has no time zone set. Attempting to set the device to the best"
+ " available suggestion."
- + " bestPhoneSuggestion=" + bestPhoneSuggestion
+ + " bestTelephonySuggestion=" + bestTelephonySuggestion
+ ", detectionReason=" + detectionReason;
Slog.i(LOG_TAG, cause);
- setDeviceTimeZoneIfRequired(ORIGIN_PHONE, newZoneId, cause);
+ setDeviceTimeZoneIfRequired(ORIGIN_TELEPHONY, newZoneId, cause);
return;
}
- boolean suggestionGoodEnough = bestPhoneSuggestion.score >= PHONE_SCORE_USAGE_THRESHOLD;
+ boolean suggestionGoodEnough =
+ bestTelephonySuggestion.score >= TELEPHONY_SCORE_USAGE_THRESHOLD;
if (!suggestionGoodEnough) {
if (DBG) {
Slog.d(LOG_TAG, "Best suggestion not good enough."
- + " bestPhoneSuggestion=" + bestPhoneSuggestion
+ + " bestTelephonySuggestion=" + bestTelephonySuggestion
+ ", detectionReason=" + detectionReason);
}
return;
@@ -297,16 +303,16 @@
// zone ID.
if (newZoneId == null) {
Slog.w(LOG_TAG, "Empty zone suggestion scored higher than expected. This is an error:"
- + " bestPhoneSuggestion=" + bestPhoneSuggestion
+ + " bestTelephonySuggestion=" + bestTelephonySuggestion
+ " detectionReason=" + detectionReason);
return;
}
- String zoneId = bestPhoneSuggestion.suggestion.getZoneId();
+ String zoneId = bestTelephonySuggestion.suggestion.getZoneId();
String cause = "Found good suggestion."
- + ", bestPhoneSuggestion=" + bestPhoneSuggestion
+ + ", bestTelephonySuggestion=" + bestTelephonySuggestion
+ ", detectionReason=" + detectionReason;
- setDeviceTimeZoneIfRequired(ORIGIN_PHONE, zoneId, cause);
+ setDeviceTimeZoneIfRequired(ORIGIN_TELEPHONY, zoneId, cause);
}
@GuardedBy("this")
@@ -372,15 +378,15 @@
@GuardedBy("this")
@Nullable
- private QualifiedPhoneTimeZoneSuggestion findBestPhoneSuggestion() {
- QualifiedPhoneTimeZoneSuggestion bestSuggestion = null;
+ private QualifiedTelephonyTimeZoneSuggestion findBestTelephonySuggestion() {
+ QualifiedTelephonyTimeZoneSuggestion bestSuggestion = null;
- // Iterate over the latest QualifiedPhoneTimeZoneSuggestion objects received for each phone
- // and find the best. Note that we deliberately do not look at age: the caller can
+ // Iterate over the latest QualifiedTelephonyTimeZoneSuggestion objects received for each
+ // slotIndex and find the best. Note that we deliberately do not look at age: the caller can
// rate-limit so age is not a strong indicator of confidence. Instead, the callers are
// expected to withdraw suggestions they no longer have confidence in.
for (int i = 0; i < mSuggestionBySlotIndex.size(); i++) {
- QualifiedPhoneTimeZoneSuggestion candidateSuggestion =
+ QualifiedTelephonyTimeZoneSuggestion candidateSuggestion =
mSuggestionBySlotIndex.valueAt(i);
if (candidateSuggestion == null) {
// Unexpected
@@ -404,13 +410,13 @@
}
/**
- * Returns the current best phone suggestion. Not intended for general use: it is used during
- * tests to check strategy behavior.
+ * Returns the current best telephony suggestion. Not intended for general use: it is used
+ * during tests to check strategy behavior.
*/
@VisibleForTesting
@Nullable
- public synchronized QualifiedPhoneTimeZoneSuggestion findBestPhoneSuggestionForTests() {
- return findBestPhoneSuggestion();
+ public synchronized QualifiedTelephonyTimeZoneSuggestion findBestTelephonySuggestionForTests() {
+ return findBestTelephonySuggestion();
}
@Override
@@ -447,7 +453,7 @@
mTimeZoneChangesLog.dump(ipw);
ipw.decreaseIndent(); // level 2
- ipw.println("Phone suggestion history:");
+ ipw.println("Telephony suggestion history:");
ipw.increaseIndent(); // level 2
mSuggestionBySlotIndex.dump(ipw);
ipw.decreaseIndent(); // level 2
@@ -459,18 +465,19 @@
* A method used to inspect strategy state during tests. Not intended for general use.
*/
@VisibleForTesting
- public synchronized QualifiedPhoneTimeZoneSuggestion getLatestPhoneSuggestion(int slotIndex) {
+ public synchronized QualifiedTelephonyTimeZoneSuggestion getLatestTelephonySuggestion(
+ int slotIndex) {
return mSuggestionBySlotIndex.get(slotIndex);
}
/**
- * A {@link PhoneTimeZoneSuggestion} with additional qualifying metadata.
+ * A {@link TelephonyTimeZoneSuggestion} with additional qualifying metadata.
*/
@VisibleForTesting
- public static class QualifiedPhoneTimeZoneSuggestion {
+ public static class QualifiedTelephonyTimeZoneSuggestion {
@VisibleForTesting
- public final PhoneTimeZoneSuggestion suggestion;
+ public final TelephonyTimeZoneSuggestion suggestion;
/**
* The score the suggestion has been given. This can be used to rank against other
@@ -480,7 +487,8 @@
public final int score;
@VisibleForTesting
- public QualifiedPhoneTimeZoneSuggestion(PhoneTimeZoneSuggestion suggestion, int score) {
+ public QualifiedTelephonyTimeZoneSuggestion(
+ TelephonyTimeZoneSuggestion suggestion, int score) {
this.suggestion = suggestion;
this.score = score;
}
@@ -493,7 +501,7 @@
if (o == null || getClass() != o.getClass()) {
return false;
}
- QualifiedPhoneTimeZoneSuggestion that = (QualifiedPhoneTimeZoneSuggestion) o;
+ QualifiedTelephonyTimeZoneSuggestion that = (QualifiedTelephonyTimeZoneSuggestion) o;
return score == that.score
&& suggestion.equals(that.suggestion);
}
@@ -505,7 +513,7 @@
@Override
public String toString() {
- return "QualifiedPhoneTimeZoneSuggestion{"
+ return "QualifiedTelephonyTimeZoneSuggestion{"
+ "suggestion=" + suggestion
+ ", score=" + score
+ '}';
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 4f010d5..e3b1152c 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -383,36 +383,38 @@
if (mCurrentUserId == userId) {
return;
}
- UserState userState = mUserStates.get(mCurrentUserId);
- List<SessionState> sessionStatesToRelease = new ArrayList<>();
- for (SessionState sessionState : userState.sessionStateMap.values()) {
- if (sessionState.session != null && !sessionState.isRecordingSession) {
- sessionStatesToRelease.add(sessionState);
- }
- }
- for (SessionState sessionState : sessionStatesToRelease) {
- try {
- sessionState.session.release();
- } catch (RemoteException e) {
- Slog.e(TAG, "error in release", e);
- }
- clearSessionAndNotifyClientLocked(sessionState);
- }
-
- for (Iterator<ComponentName> it = userState.serviceStateMap.keySet().iterator();
- it.hasNext(); ) {
- ComponentName component = it.next();
- ServiceState serviceState = userState.serviceStateMap.get(component);
- if (serviceState != null && serviceState.sessionTokens.isEmpty()) {
- if (serviceState.callback != null) {
- try {
- serviceState.service.unregisterCallback(serviceState.callback);
- } catch (RemoteException e) {
- Slog.e(TAG, "error in unregisterCallback", e);
- }
+ if (mUserStates.contains(mCurrentUserId)) {
+ UserState userState = mUserStates.get(mCurrentUserId);
+ List<SessionState> sessionStatesToRelease = new ArrayList<>();
+ for (SessionState sessionState : userState.sessionStateMap.values()) {
+ if (sessionState.session != null && !sessionState.isRecordingSession) {
+ sessionStatesToRelease.add(sessionState);
}
- mContext.unbindService(serviceState.connection);
- it.remove();
+ }
+ for (SessionState sessionState : sessionStatesToRelease) {
+ try {
+ sessionState.session.release();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in release", e);
+ }
+ clearSessionAndNotifyClientLocked(sessionState);
+ }
+
+ for (Iterator<ComponentName> it = userState.serviceStateMap.keySet().iterator();
+ it.hasNext(); ) {
+ ComponentName component = it.next();
+ ServiceState serviceState = userState.serviceStateMap.get(component);
+ if (serviceState != null && serviceState.sessionTokens.isEmpty()) {
+ if (serviceState.callback != null) {
+ try {
+ serviceState.service.unregisterCallback(serviceState.callback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in unregisterCallback", e);
+ }
+ }
+ mContext.unbindService(serviceState.connection);
+ it.remove();
+ }
}
}
@@ -490,6 +492,10 @@
userState.mainSessionToken = null;
mUserStates.remove(userId);
+
+ if (userId == mCurrentUserId) {
+ switchUser(UserHandle.USER_SYSTEM);
+ }
}
}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 3d9f11f..339ff6b 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -22,6 +22,7 @@
"services.net",
"service-jobscheduler",
"service-permission",
+ "service-blobstore",
"androidx.test.runner",
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
new file mode 100644
index 0000000..16dde42
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2020 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.blob;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.server.blob.BlobStoreConfig.SESSION_EXPIRY_TIMEOUT_MILLIS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.app.blob.BlobHandle;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArrayMap;
+import android.util.LongSparseArray;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.blob.BlobStoreManagerService.Injector;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.io.File;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class BlobStoreManagerServiceTest {
+ private Context mContext;
+ private Handler mHandler;
+ private BlobStoreManagerService mService;
+
+ private MockitoSession mMockitoSession;
+
+ @Mock
+ private File mBlobsDir;
+
+ private LongSparseArray<BlobStoreSession> mUserSessions;
+ private ArrayMap<BlobHandle, BlobMetadata> mUserBlobs;
+
+ private static final String TEST_PKG1 = "com.example1";
+ private static final String TEST_PKG2 = "com.example2";
+ private static final String TEST_PKG3 = "com.example3";
+
+ private static final int TEST_UID1 = 10001;
+ private static final int TEST_UID2 = 10002;
+ private static final int TEST_UID3 = 10003;
+
+ @Before
+ public void setUp() {
+ // Share classloader to allow package private access.
+ System.setProperty("dexmaker.share_classloader", "true");
+
+ mMockitoSession = mockitoSession()
+ .initMocks(this)
+ .strictness(Strictness.LENIENT)
+ .mockStatic(BlobStoreConfig.class)
+ .startMocking();
+
+ doReturn(mBlobsDir).when(() -> BlobStoreConfig.getBlobsDir());
+ doReturn(true).when(mBlobsDir).exists();
+ doReturn(new File[0]).when(mBlobsDir).listFiles();
+
+ mContext = InstrumentationRegistry.getTargetContext();
+ mHandler = new TestHandler(Looper.getMainLooper());
+ mService = new BlobStoreManagerService(mContext, new TestInjector());
+ mUserSessions = new LongSparseArray<>();
+ mUserBlobs = new ArrayMap<>();
+
+ mService.addUserSessionsForTest(mUserSessions, UserHandle.myUserId());
+ mService.addUserBlobsForTest(mUserBlobs, UserHandle.myUserId());
+ }
+
+ @After
+ public void tearDown() {
+ if (mMockitoSession != null) {
+ mMockitoSession.finishMocking();
+ }
+ }
+
+ @Test
+ public void testHandlePackageRemoved() throws Exception {
+ // Setup sessions
+ final File sessionFile1 = mock(File.class);
+ final long sessionId1 = 11;
+ final BlobStoreSession session1 = createBlobStoreSessionMock(TEST_PKG1, TEST_UID1,
+ sessionId1, sessionFile1);
+ mUserSessions.append(sessionId1, session1);
+
+ final File sessionFile2 = mock(File.class);
+ final long sessionId2 = 25;
+ final BlobStoreSession session2 = createBlobStoreSessionMock(TEST_PKG2, TEST_UID2,
+ sessionId2, sessionFile2);
+ mUserSessions.append(sessionId2, session2);
+
+ final File sessionFile3 = mock(File.class);
+ final long sessionId3 = 37;
+ final BlobStoreSession session3 = createBlobStoreSessionMock(TEST_PKG3, TEST_UID3,
+ sessionId3, sessionFile3);
+ mUserSessions.append(sessionId3, session3);
+
+ final File sessionFile4 = mock(File.class);
+ final long sessionId4 = 48;
+ final BlobStoreSession session4 = createBlobStoreSessionMock(TEST_PKG1, TEST_UID1,
+ sessionId4, sessionFile4);
+ mUserSessions.append(sessionId4, session4);
+
+ // Setup blobs
+ final long blobId1 = 978;
+ final File blobFile1 = mock(File.class);
+ final BlobHandle blobHandle1 = BlobHandle.createWithSha256("digest1".getBytes(),
+ "label1", System.currentTimeMillis(), "tag1");
+ final BlobMetadata blobMetadata1 = createBlobMetadataMock(blobId1, blobFile1, true);
+ mUserBlobs.put(blobHandle1, blobMetadata1);
+
+ final long blobId2 = 347;
+ final File blobFile2 = mock(File.class);
+ final BlobHandle blobHandle2 = BlobHandle.createWithSha256("digest2".getBytes(),
+ "label2", System.currentTimeMillis(), "tag2");
+ final BlobMetadata blobMetadata2 = createBlobMetadataMock(blobId2, blobFile2, false);
+ mUserBlobs.put(blobHandle2, blobMetadata2);
+
+ mService.addKnownIdsForTest(sessionId1, sessionId2, sessionId3, sessionId4,
+ blobId1, blobId2);
+
+ // Invoke test method
+ mService.handlePackageRemoved(TEST_PKG1, TEST_UID1);
+
+ // Verify sessions are removed
+ verify(sessionFile1).delete();
+ verify(sessionFile2, never()).delete();
+ verify(sessionFile3, never()).delete();
+ verify(sessionFile4).delete();
+
+ assertThat(mUserSessions.size()).isEqualTo(2);
+ assertThat(mUserSessions.get(sessionId1)).isNull();
+ assertThat(mUserSessions.get(sessionId2)).isNotNull();
+ assertThat(mUserSessions.get(sessionId3)).isNotNull();
+ assertThat(mUserSessions.get(sessionId4)).isNull();
+
+ // Verify blobs are removed
+ verify(blobMetadata1).removeCommitter(TEST_PKG1, TEST_UID1);
+ verify(blobMetadata1).removeLeasee(TEST_PKG1, TEST_UID1);
+ verify(blobMetadata2).removeCommitter(TEST_PKG1, TEST_UID1);
+ verify(blobMetadata2).removeLeasee(TEST_PKG1, TEST_UID1);
+
+ verify(blobFile1, never()).delete();
+ verify(blobFile2).delete();
+
+ assertThat(mUserBlobs.size()).isEqualTo(1);
+ assertThat(mUserBlobs.get(blobHandle1)).isNotNull();
+ assertThat(mUserBlobs.get(blobHandle2)).isNull();
+
+ assertThat(mService.getKnownIdsForTest()).containsExactly(
+ sessionId2, sessionId3, blobId1);
+ }
+
+ @Test
+ public void testHandleIdleMaintenance_deleteUnknownBlobs() throws Exception {
+ // Setup blob files
+ final long testId1 = 286;
+ final File file1 = mock(File.class);
+ doReturn(String.valueOf(testId1)).when(file1).getName();
+ final long testId2 = 349;
+ final File file2 = mock(File.class);
+ doReturn(String.valueOf(testId2)).when(file2).getName();
+ final long testId3 = 7355;
+ final File file3 = mock(File.class);
+ doReturn(String.valueOf(testId3)).when(file3).getName();
+
+ doReturn(new File[] {file1, file2, file3}).when(mBlobsDir).listFiles();
+ mService.addKnownIdsForTest(testId1, testId3);
+
+ // Invoke test method
+ mService.handleIdleMaintenanceLocked();
+
+ // Verify unknown blobs are delete
+ verify(file1, never()).delete();
+ verify(file2).delete();
+ verify(file3, never()).delete();
+ }
+
+ @Test
+ public void testHandleIdleMaintenance_deleteStaleSessions() throws Exception {
+ // Setup sessions
+ final File sessionFile1 = mock(File.class);
+ doReturn(System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MILLIS + 1000)
+ .when(sessionFile1).lastModified();
+ final long sessionId1 = 342;
+ final BlobHandle blobHandle1 = mock(BlobHandle.class);
+ doReturn(System.currentTimeMillis() - 1000).when(blobHandle1).getExpiryTimeMillis();
+ final BlobStoreSession session1 = createBlobStoreSessionMock(TEST_PKG1, TEST_UID1,
+ sessionId1, sessionFile1, blobHandle1);
+ mUserSessions.append(sessionId1, session1);
+
+ final File sessionFile2 = mock(File.class);
+ doReturn(System.currentTimeMillis() - 20000)
+ .when(sessionFile2).lastModified();
+ final long sessionId2 = 4597;
+ final BlobHandle blobHandle2 = mock(BlobHandle.class);
+ doReturn(System.currentTimeMillis() + 20000).when(blobHandle2).getExpiryTimeMillis();
+ final BlobStoreSession session2 = createBlobStoreSessionMock(TEST_PKG2, TEST_UID2,
+ sessionId2, sessionFile2, blobHandle2);
+ mUserSessions.append(sessionId2, session2);
+
+ final File sessionFile3 = mock(File.class);
+ doReturn(System.currentTimeMillis() - SESSION_EXPIRY_TIMEOUT_MILLIS - 2000)
+ .when(sessionFile3).lastModified();
+ final long sessionId3 = 9484;
+ final BlobHandle blobHandle3 = mock(BlobHandle.class);
+ doReturn(System.currentTimeMillis() + 30000).when(blobHandle3).getExpiryTimeMillis();
+ final BlobStoreSession session3 = createBlobStoreSessionMock(TEST_PKG3, TEST_UID3,
+ sessionId3, sessionFile3, blobHandle3);
+ mUserSessions.append(sessionId3, session3);
+
+ mService.addKnownIdsForTest(sessionId1, sessionId2, sessionId3);
+
+ // Invoke test method
+ mService.handleIdleMaintenanceLocked();
+
+ // Verify stale sessions are removed
+ verify(sessionFile1).delete();
+ verify(sessionFile2, never()).delete();
+ verify(sessionFile3).delete();
+
+ assertThat(mUserSessions.size()).isEqualTo(1);
+ assertThat(mUserSessions.get(sessionId2)).isNotNull();
+
+ assertThat(mService.getKnownIdsForTest()).containsExactly(sessionId2);
+ }
+
+ @Test
+ public void testHandleIdleMaintenance_deleteStaleBlobs() throws Exception {
+ // Setup blobs
+ final long blobId1 = 3489;
+ final File blobFile1 = mock(File.class);
+ final BlobHandle blobHandle1 = BlobHandle.createWithSha256("digest1".getBytes(),
+ "label1", System.currentTimeMillis() - 2000, "tag1");
+ final BlobMetadata blobMetadata1 = createBlobMetadataMock(blobId1, blobFile1, true);
+ mUserBlobs.put(blobHandle1, blobMetadata1);
+
+ final long blobId2 = 78974;
+ final File blobFile2 = mock(File.class);
+ final BlobHandle blobHandle2 = BlobHandle.createWithSha256("digest2".getBytes(),
+ "label2", System.currentTimeMillis() + 30000, "tag2");
+ final BlobMetadata blobMetadata2 = createBlobMetadataMock(blobId2, blobFile2, true);
+ mUserBlobs.put(blobHandle2, blobMetadata2);
+
+ final long blobId3 = 97;
+ final File blobFile3 = mock(File.class);
+ final BlobHandle blobHandle3 = BlobHandle.createWithSha256("digest3".getBytes(),
+ "label3", System.currentTimeMillis() + 4400000, "tag3");
+ final BlobMetadata blobMetadata3 = createBlobMetadataMock(blobId3, blobFile3, false);
+ mUserBlobs.put(blobHandle3, blobMetadata3);
+
+ mService.addKnownIdsForTest(blobId1, blobId2, blobId3);
+
+ // Invoke test method
+ mService.handleIdleMaintenanceLocked();
+
+ // Verify stale blobs are removed
+ verify(blobFile1).delete();
+ verify(blobFile2, never()).delete();
+ verify(blobFile3).delete();
+
+ assertThat(mUserBlobs.size()).isEqualTo(1);
+ assertThat(mUserBlobs.get(blobHandle2)).isNotNull();
+
+ assertThat(mService.getKnownIdsForTest()).containsExactly(blobId2);
+ }
+
+ private BlobStoreSession createBlobStoreSessionMock(String ownerPackageName, int ownerUid,
+ long sessionId, File sessionFile) {
+ return createBlobStoreSessionMock(ownerPackageName, ownerUid, sessionId, sessionFile,
+ mock(BlobHandle.class));
+ }
+ private BlobStoreSession createBlobStoreSessionMock(String ownerPackageName, int ownerUid,
+ long sessionId, File sessionFile, BlobHandle blobHandle) {
+ final BlobStoreSession session = mock(BlobStoreSession.class);
+ doReturn(ownerPackageName).when(session).getOwnerPackageName();
+ doReturn(ownerUid).when(session).getOwnerUid();
+ doReturn(sessionId).when(session).getSessionId();
+ doReturn(sessionFile).when(session).getSessionFile();
+ doReturn(blobHandle).when(session).getBlobHandle();
+ return session;
+ }
+
+ private BlobMetadata createBlobMetadataMock(long blobId, File blobFile, boolean hasLeases) {
+ final BlobMetadata blobMetadata = mock(BlobMetadata.class);
+ doReturn(blobId).when(blobMetadata).getBlobId();
+ doReturn(blobFile).when(blobMetadata).getBlobFile();
+ doReturn(hasLeases).when(blobMetadata).hasLeases();
+ return blobMetadata;
+ }
+
+ private class TestHandler extends Handler {
+ TestHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void dispatchMessage(Message msg) {
+ // Ignore all messages
+ }
+ }
+
+ private class TestInjector extends Injector {
+ @Override
+ public Handler initializeMessageHandler() {
+ return mHandler;
+ }
+ }
+}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 8381205..f990810 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -46,7 +46,6 @@
"service-appsearch",
"service-jobscheduler",
"service-permission",
- "service-blobstore",
// TODO: remove once Android migrates to JUnit 4.12,
// which provides assertThrows
"testng",
diff --git a/services/tests/servicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
deleted file mode 100644
index ff728e7..0000000
--- a/services/tests/servicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2020 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.blob;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.blob.BlobHandle;
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.UserHandle;
-import android.platform.test.annotations.Presubmit;
-import android.util.ArrayMap;
-import android.util.LongSparseArray;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.server.blob.BlobStoreManagerService.Injector;
-import com.android.server.blob.BlobStoreManagerService.SessionStateChangeListener;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-@Presubmit
-public class BlobStoreManagerServiceTest {
- private Context mContext;
- private Handler mHandler;
- private BlobStoreManagerService mService;
-
- private LongSparseArray<BlobStoreSession> mUserSessions;
- private ArrayMap<BlobHandle, BlobMetadata> mUserBlobs;
-
- private SessionStateChangeListener mStateChangeListener;
-
- private static final String TEST_PKG1 = "com.example1";
- private static final String TEST_PKG2 = "com.example2";
- private static final String TEST_PKG3 = "com.example3";
-
- private static final int TEST_UID1 = 10001;
- private static final int TEST_UID2 = 10002;
- private static final int TEST_UID3 = 10003;
-
- @Before
- public void setUp() {
- // Share classloader to allow package private access.
- System.setProperty("dexmaker.share_classloader", "true");
-
- mContext = InstrumentationRegistry.getTargetContext();
- mHandler = new TestHandler(Looper.getMainLooper());
- mService = new BlobStoreManagerService(mContext, new TestInjector());
- mUserSessions = new LongSparseArray<>();
- mUserBlobs = new ArrayMap<>();
-
- mService.addUserSessionsForTest(mUserSessions, UserHandle.myUserId());
- mService.addUserBlobsForTest(mUserBlobs, UserHandle.myUserId());
-
- mStateChangeListener = mService.new SessionStateChangeListener();
- }
-
- @Test
- public void testHandlePackageRemoved() throws Exception {
- // Setup sessions
- final File sessionFile1 = mock(File.class);
- final long sessionId1 = 11;
- final BlobStoreSession session1 = createBlobStoreSessionMock(TEST_PKG1, TEST_UID1,
- sessionId1, sessionFile1);
- mUserSessions.append(sessionId1, session1);
-
- final File sessionFile2 = mock(File.class);
- final long sessionId2 = 25;
- final BlobStoreSession session2 = createBlobStoreSessionMock(TEST_PKG2, TEST_UID2,
- sessionId2, sessionFile2);
- mUserSessions.append(sessionId2, session2);
-
- final File sessionFile3 = mock(File.class);
- final long sessionId3 = 37;
- final BlobStoreSession session3 = createBlobStoreSessionMock(TEST_PKG3, TEST_UID3,
- sessionId3, sessionFile3);
- mUserSessions.append(sessionId3, session3);
-
- final File sessionFile4 = mock(File.class);
- final long sessionId4 = 48;
- final BlobStoreSession session4 = createBlobStoreSessionMock(TEST_PKG1, TEST_UID1,
- sessionId4, sessionFile4);
- mUserSessions.append(sessionId4, session4);
-
- // Setup blobs
- final File blobFile1 = mock(File.class);
- final BlobHandle blobHandle1 = BlobHandle.createWithSha256("digest1".getBytes(),
- "label1", System.currentTimeMillis(), "tag1");
- final BlobMetadata blobMetadata1 = createBlobMetadataMock(blobFile1, true);
- mUserBlobs.put(blobHandle1, blobMetadata1);
-
- final File blobFile2 = mock(File.class);
- final BlobHandle blobHandle2 = BlobHandle.createWithSha256("digest2".getBytes(),
- "label2", System.currentTimeMillis(), "tag2");
- final BlobMetadata blobMetadata2 = createBlobMetadataMock(blobFile2, false);
- mUserBlobs.put(blobHandle2, blobMetadata2);
-
- // Invoke test method
- mService.handlePackageRemoved(TEST_PKG1, TEST_UID1);
-
- // Verify sessions are removed
- verify(sessionFile1).delete();
- verify(sessionFile2, never()).delete();
- verify(sessionFile3, never()).delete();
- verify(sessionFile4).delete();
-
- assertThat(mUserSessions.size()).isEqualTo(2);
- assertThat(mUserSessions.get(sessionId1)).isNull();
- assertThat(mUserSessions.get(sessionId2)).isNotNull();
- assertThat(mUserSessions.get(sessionId3)).isNotNull();
- assertThat(mUserSessions.get(sessionId4)).isNull();
-
- // Verify blobs are removed
- verify(blobMetadata1).removeCommitter(TEST_PKG1, TEST_UID1);
- verify(blobMetadata1).removeLeasee(TEST_PKG1, TEST_UID1);
- verify(blobMetadata2).removeCommitter(TEST_PKG1, TEST_UID1);
- verify(blobMetadata2).removeLeasee(TEST_PKG1, TEST_UID1);
-
- verify(blobFile1, never()).delete();
- verify(blobFile2).delete();
-
- assertThat(mUserBlobs.size()).isEqualTo(1);
- assertThat(mUserBlobs.get(blobHandle1)).isNotNull();
- assertThat(mUserBlobs.get(blobHandle2)).isNull();
- }
-
- private BlobStoreSession createBlobStoreSessionMock(String ownerPackageName, int ownerUid,
- long sessionId, File sessionFile) {
- final BlobStoreSession session = mock(BlobStoreSession.class);
- when(session.getOwnerPackageName()).thenReturn(ownerPackageName);
- when(session.getOwnerUid()).thenReturn(ownerUid);
- when(session.getSessionId()).thenReturn(sessionId);
- when(session.getSessionFile()).thenReturn(sessionFile);
- return session;
- }
-
- private BlobMetadata createBlobMetadataMock(File blobFile, boolean hasLeases) {
- final BlobMetadata blobMetadata = mock(BlobMetadata.class);
- when(blobMetadata.getBlobFile()).thenReturn(blobFile);
- when(blobMetadata.hasLeases()).thenReturn(hasLeases);
- return blobMetadata;
- }
-
- private class TestHandler extends Handler {
- TestHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void dispatchMessage(Message msg) {
- // Ignore all messages
- }
- }
-
- private class TestInjector extends Injector {
- @Override
- public Handler initializeMessageHandler() {
- return mHandler;
- }
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index bfe0c15..d4edab4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -24,6 +24,7 @@
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.content.pm.PackageInstaller;
+import android.platform.test.annotations.Presubmit;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
@@ -57,6 +58,7 @@
import java.util.List;
@RunWith(AndroidJUnit4.class)
+@Presubmit
public class PackageInstallerSessionTest {
@Rule
public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 218f43c..2eeeb3e 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -30,7 +30,7 @@
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.HandlerThread;
@@ -80,35 +80,35 @@
}
@Test(expected = SecurityException.class)
- public void testSuggestPhoneTime_withoutPermission() {
+ public void testSuggestTelephonyTime_withoutPermission() {
doThrow(new SecurityException("Mock"))
.when(mMockContext).enforceCallingPermission(anyString(), any());
- PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
+ TelephonyTimeSuggestion timeSuggestion = createTelephonyTimeSuggestion();
try {
- mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
+ mTimeDetectorService.suggestTelephonyTime(timeSuggestion);
fail();
} finally {
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE),
+ eq(android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE),
anyString());
}
}
@Test
- public void testSuggestPhoneTime() throws Exception {
+ public void testSuggestTelephonyTime() throws Exception {
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
- PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
- mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
+ TelephonyTimeSuggestion timeSuggestion = createTelephonyTimeSuggestion();
+ mTimeDetectorService.suggestTelephonyTime(timeSuggestion);
mTestHandler.assertTotalMessagesEnqueued(1);
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE),
+ eq(android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE),
anyString());
mTestHandler.waitForMessagesToBeProcessed();
- mStubbedTimeDetectorStrategy.verifySuggestPhoneTimeCalled(phoneTimeSuggestion);
+ mStubbedTimeDetectorStrategy.verifySuggestTelephonyTimeCalled(timeSuggestion);
}
@Test(expected = SecurityException.class)
@@ -199,10 +199,10 @@
mStubbedTimeDetectorStrategy.verifyHandleAutoTimeDetectionChangedCalled();
}
- private static PhoneTimeSuggestion createPhoneTimeSuggestion() {
+ private static TelephonyTimeSuggestion createTelephonyTimeSuggestion() {
int slotIndex = 1234;
TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
- return new PhoneTimeSuggestion.Builder(slotIndex)
+ return new TelephonyTimeSuggestion.Builder(slotIndex)
.setUtcTime(timeValue)
.build();
}
@@ -220,7 +220,7 @@
private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
// Call tracking.
- private PhoneTimeSuggestion mLastPhoneSuggestion;
+ private TelephonyTimeSuggestion mLastTelephonySuggestion;
private ManualTimeSuggestion mLastManualSuggestion;
private NetworkTimeSuggestion mLastNetworkSuggestion;
private boolean mHandleAutoTimeDetectionChangedCalled;
@@ -231,8 +231,8 @@
}
@Override
- public void suggestPhoneTime(PhoneTimeSuggestion timeSuggestion) {
- mLastPhoneSuggestion = timeSuggestion;
+ public void suggestTelephonyTime(TelephonyTimeSuggestion timeSuggestion) {
+ mLastTelephonySuggestion = timeSuggestion;
}
@Override
@@ -256,15 +256,15 @@
}
void resetCallTracking() {
- mLastPhoneSuggestion = null;
+ mLastTelephonySuggestion = null;
mLastManualSuggestion = null;
mLastNetworkSuggestion = null;
mHandleAutoTimeDetectionChangedCalled = false;
mDumpCalled = false;
}
- void verifySuggestPhoneTimeCalled(PhoneTimeSuggestion expectedSuggestion) {
- assertEquals(expectedSuggestion, mLastPhoneSuggestion);
+ void verifySuggestTelephonyTimeCalled(TelephonyTimeSuggestion expectedSuggestion) {
+ assertEquals(expectedSuggestion, mLastTelephonySuggestion);
}
public void verifySuggestManualTimeCalled(ManualTimeSuggestion expectedSuggestion) {
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index d940a6a..803b245 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -24,7 +24,7 @@
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timedetector.TelephonyTimeSuggestion;
import android.icu.util.Calendar;
import android.icu.util.GregorianCalendar;
import android.icu.util.TimeZone;
@@ -52,7 +52,7 @@
*/
private static final long ARBITRARY_TEST_TIME_MILLIS = createUtcTime(2018, 1, 1, 12, 0, 0);
- private static final int ARBITRARY_PHONE_ID = 123456;
+ private static final int ARBITRARY_SLOT_INDEX = 123456;
private Script mScript;
@@ -62,51 +62,51 @@
}
@Test
- public void testSuggestPhoneTime_autoTimeEnabled() {
+ public void testSuggestTelephonyTime_autoTimeEnabled() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
- int phoneId = ARBITRARY_PHONE_ID;
+ int slotIndex = ARBITRARY_SLOT_INDEX;
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- PhoneTimeSuggestion timeSuggestion =
- mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ TelephonyTimeSuggestion timeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
mScript.simulateTimePassing()
- .simulatePhoneTimeSuggestion(timeSuggestion);
+ .simulateTelephonyTimeSuggestion(timeSuggestion);
long expectedSystemClockMillis =
mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
mScript.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
}
@Test
- public void testSuggestPhoneTime_emptySuggestionIgnored() {
+ public void testSuggestTelephonyTime_emptySuggestionIgnored() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
- int phoneId = ARBITRARY_PHONE_ID;
- PhoneTimeSuggestion timeSuggestion =
- mScript.generatePhoneTimeSuggestion(phoneId, null);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion)
+ int slotIndex = ARBITRARY_SLOT_INDEX;
+ TelephonyTimeSuggestion timeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, null);
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, null);
+ .assertLatestTelephonySuggestion(slotIndex, null);
}
@Test
- public void testSuggestPhoneTime_systemClockThreshold() {
+ public void testSuggestTelephonyTime_systemClockThreshold() {
final int systemClockUpdateThresholdMillis = 1000;
final int clockIncrementMillis = 100;
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeThresholds(systemClockUpdateThresholdMillis)
.pokeAutoTimeDetectionEnabled(true);
- int phoneId = ARBITRARY_PHONE_ID;
+ int slotIndex = ARBITRARY_SLOT_INDEX;
// Send the first time signal. It should be used.
{
- PhoneTimeSuggestion timeSuggestion1 =
- mScript.generatePhoneTimeSuggestion(phoneId, ARBITRARY_TEST_TIME_MILLIS);
+ TelephonyTimeSuggestion timeSuggestion1 =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME_MILLIS);
// Increment the the device clocks to simulate the passage of time.
mScript.simulateTimePassing(clockIncrementMillis);
@@ -114,151 +114,151 @@
long expectedSystemClockMillis1 =
mScript.calculateTimeInMillisForNow(timeSuggestion1.getUtcTime());
- mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
}
// Now send another time signal, but one that is too similar to the last one and should be
// stored, but not used to set the system clock.
{
int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
- PhoneTimeSuggestion timeSuggestion2 = mScript.generatePhoneTimeSuggestion(
- phoneId, mScript.peekSystemClockMillis() + underThresholdMillis);
+ TelephonyTimeSuggestion timeSuggestion2 = mScript.generateTelephonyTimeSuggestion(
+ slotIndex, mScript.peekSystemClockMillis() + underThresholdMillis);
mScript.simulateTimePassing(clockIncrementMillis)
- .simulatePhoneTimeSuggestion(timeSuggestion2)
+ .simulateTelephonyTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
}
// Now send another time signal, but one that is on the threshold and so should be used.
{
- PhoneTimeSuggestion timeSuggestion3 = mScript.generatePhoneTimeSuggestion(
- phoneId,
+ TelephonyTimeSuggestion timeSuggestion3 = mScript.generateTelephonyTimeSuggestion(
+ slotIndex,
mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis3 =
mScript.calculateTimeInMillisForNow(timeSuggestion3.getUtcTime());
- mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion3)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis3)
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion3);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion3);
}
}
@Test
- public void testSuggestPhoneTime_multiplePhoneIdsAndBucketing() {
+ public void testSuggestTelephonyTime_multipleSlotIndexsAndBucketing() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
- // There are 2 phones in this test. Phone 2 has a different idea of the current time.
- // phone1Id < phone2Id (which is important because the strategy uses the lowest ID when
- // multiple phone suggestions are available.
- int phone1Id = ARBITRARY_PHONE_ID;
- int phone2Id = ARBITRARY_PHONE_ID + 1;
- long phone1TimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- long phone2TimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(1).toMillis();
+ // There are 2 slotIndexes in this test. slotIndex1 and slotIndex2 have different opinions
+ // about the current time. slotIndex1 < slotIndex2 (which is important because the strategy
+ // uses the lowest slotIndex when multiple telephony suggestions are available.
+ int slotIndex1 = ARBITRARY_SLOT_INDEX;
+ int slotIndex2 = ARBITRARY_SLOT_INDEX + 1;
+ long slotIndex1TimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+ long slotIndex2TimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(1).toMillis();
- // Make a suggestion with phone2Id.
+ // Make a suggestion with slotIndex2.
{
- PhoneTimeSuggestion phone2TimeSuggestion =
- mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+ TelephonyTimeSuggestion slotIndex2TimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis);
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(phone2TimeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(slotIndex2TimeSuggestion.getUtcTime());
- mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+ mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
- .assertLatestPhoneSuggestion(phone1Id, null)
- .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex1, null)
+ .assertLatestTelephonySuggestion(slotIndex2, slotIndex2TimeSuggestion);
}
mScript.simulateTimePassing();
- // Now make a different suggestion with phone1Id.
+ // Now make a different suggestion with slotIndex1.
{
- PhoneTimeSuggestion phone1TimeSuggestion =
- mScript.generatePhoneTimeSuggestion(phone1Id, phone1TimeMillis);
+ TelephonyTimeSuggestion slotIndex1TimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1TimeMillis);
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(phone1TimeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(slotIndex1TimeSuggestion.getUtcTime());
- mScript.simulatePhoneTimeSuggestion(phone1TimeSuggestion)
+ mScript.simulateTelephonyTimeSuggestion(slotIndex1TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
- .assertLatestPhoneSuggestion(phone1Id, phone1TimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex1, slotIndex1TimeSuggestion);
}
mScript.simulateTimePassing();
- // Make another suggestion with phone2Id. It should be stored but not used because the
- // phone1Id suggestion will still "win".
+ // Make another suggestion with slotIndex2. It should be stored but not used because the
+ // slotIndex1 suggestion will still "win".
{
- PhoneTimeSuggestion phone2TimeSuggestion =
- mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+ TelephonyTimeSuggestion slotIndex2TimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis);
mScript.simulateTimePassing();
- mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+ mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex2, slotIndex2TimeSuggestion);
}
- // Let enough time pass that phone1Id's suggestion should now be too old.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.PHONE_BUCKET_SIZE_MILLIS);
+ // Let enough time pass that slotIndex1's suggestion should now be too old.
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.TELEPHONY_BUCKET_SIZE_MILLIS);
- // Make another suggestion with phone2Id. It should be used because the phoneId1
+ // Make another suggestion with slotIndex2. It should be used because the slotIndex1
// is in an older "bucket".
{
- PhoneTimeSuggestion phone2TimeSuggestion =
- mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+ TelephonyTimeSuggestion slotIndex2TimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis);
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(phone2TimeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(slotIndex2TimeSuggestion.getUtcTime());
- mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+ mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
- .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex2, slotIndex2TimeSuggestion);
}
}
@Test
- public void testSuggestPhoneTime_autoTimeDisabled() {
+ public void testSuggestTelephonyTime_autoTimeDisabled() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(false);
- int phoneId = ARBITRARY_PHONE_ID;
- PhoneTimeSuggestion timeSuggestion =
- mScript.generatePhoneTimeSuggestion(phoneId, ARBITRARY_TEST_TIME_MILLIS);
+ int slotIndex = ARBITRARY_SLOT_INDEX;
+ TelephonyTimeSuggestion timeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME_MILLIS);
mScript.simulateTimePassing()
- .simulatePhoneTimeSuggestion(timeSuggestion)
+ .simulateTelephonyTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
}
@Test
- public void testSuggestPhoneTime_invalidNitzReferenceTimesIgnored() {
+ public void testSuggestTelephonyTime_invalidNitzReferenceTimesIgnored() {
final int systemClockUpdateThreshold = 2000;
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeThresholds(systemClockUpdateThreshold)
.pokeAutoTimeDetectionEnabled(true);
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- int phoneId = ARBITRARY_PHONE_ID;
+ int slotIndex = ARBITRARY_SLOT_INDEX;
- PhoneTimeSuggestion timeSuggestion1 =
- mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ TelephonyTimeSuggestion timeSuggestion1 =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
- // Initialize the strategy / device with a time set from a phone suggestion.
+ // Initialize the strategy / device with a time set from a telephony suggestion.
mScript.simulateTimePassing();
long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(utcTime1);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// The UTC time increment should be larger than the system clock update threshold so we
// know it shouldn't be ignored for other reasons.
@@ -269,11 +269,11 @@
long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
- PhoneTimeSuggestion timeSuggestion2 =
- createPhoneTimeSuggestion(phoneId, utcTime2);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
+ TelephonyTimeSuggestion timeSuggestion2 =
+ createTelephonyTimeSuggestion(slotIndex, utcTime2);
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Now supply a new signal that has an obviously bogus reference time : substantially in the
// future.
@@ -281,36 +281,36 @@
utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
referenceTimeInFutureMillis, validUtcTimeMillis);
- PhoneTimeSuggestion timeSuggestion3 =
- createPhoneTimeSuggestion(phoneId, utcTime3);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
+ TelephonyTimeSuggestion timeSuggestion3 =
+ createTelephonyTimeSuggestion(slotIndex, utcTime3);
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion3)
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Just to prove validUtcTimeMillis is valid.
long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
validReferenceTimeMillis, validUtcTimeMillis);
long expectedSystemClockMillis4 = mScript.calculateTimeInMillisForNow(utcTime4);
- PhoneTimeSuggestion timeSuggestion4 =
- createPhoneTimeSuggestion(phoneId, utcTime4);
- mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
+ TelephonyTimeSuggestion timeSuggestion4 =
+ createTelephonyTimeSuggestion(slotIndex, utcTime4);
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion4)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4)
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion4);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion4);
}
@Test
- public void testSuggestPhoneTime_timeDetectionToggled() {
+ public void testSuggestTelephonyTime_timeDetectionToggled() {
final int clockIncrementMillis = 100;
final int systemClockUpdateThreshold = 2000;
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeThresholds(systemClockUpdateThreshold)
.pokeAutoTimeDetectionEnabled(false);
- int phoneId = ARBITRARY_PHONE_ID;
+ int slotIndex = ARBITRARY_SLOT_INDEX;
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- PhoneTimeSuggestion timeSuggestion1 =
- mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ TelephonyTimeSuggestion timeSuggestion1 =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
// Simulate time passing.
@@ -318,9 +318,9 @@
// Simulate the time signal being received. It should not be used because auto time
// detection is off but it should be recorded.
- mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion1)
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Simulate more time passing.
mScript.simulateTimePassing(clockIncrementMillis);
@@ -330,17 +330,17 @@
// Turn on auto time detection.
mScript.simulateAutoTimeDetectionToggle()
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Turn off auto time detection.
mScript.simulateAutoTimeDetectionToggle()
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Receive another valid time signal.
// It should be on the threshold and accounting for the clock increments.
- PhoneTimeSuggestion timeSuggestion2 = mScript.generatePhoneTimeSuggestion(
- phoneId, mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
+ TelephonyTimeSuggestion timeSuggestion2 = mScript.generateTelephonyTimeSuggestion(
+ slotIndex, mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
// Simulate more time passing.
mScript.simulateTimePassing(clockIncrementMillis);
@@ -350,45 +350,45 @@
// The new time, though valid, should not be set in the system clock because auto time is
// disabled.
- mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
// Turn on auto time detection.
mScript.simulateAutoTimeDetectionToggle()
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2)
- .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+ .assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
}
@Test
- public void testSuggestPhoneTime_maxSuggestionAge() {
+ public void testSuggestTelephonyTime_maxSuggestionAge() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
- int phoneId = ARBITRARY_PHONE_ID;
+ int slotIndex = ARBITRARY_SLOT_INDEX;
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- PhoneTimeSuggestion phoneSuggestion =
- mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ TelephonyTimeSuggestion telephonySuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(phoneSuggestion.getUtcTime());
- mScript.simulatePhoneTimeSuggestion(phoneSuggestion)
+ mScript.calculateTimeInMillisForNow(telephonySuggestion.getUtcTime());
+ mScript.simulateTelephonyTimeSuggestion(telephonySuggestion)
.verifySystemClockWasSetAndResetCallTracking(
expectedSystemClockMillis /* expectedNetworkBroadcast */)
- .assertLatestPhoneSuggestion(phoneId, phoneSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
- // Look inside and check what the strategy considers the current best phone suggestion.
- assertEquals(phoneSuggestion, mScript.peekBestPhoneSuggestion());
+ // Look inside and check what the strategy considers the current best telephony suggestion.
+ assertEquals(telephonySuggestion, mScript.peekBestTelephonySuggestion());
- // Simulate time passing, long enough that phoneSuggestion is now too old.
+ // Simulate time passing, long enough that telephonySuggestion is now too old.
mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS);
- // Look inside and check what the strategy considers the current best phone suggestion. It
- // should still be the, it's just no longer used.
- assertNull(mScript.peekBestPhoneSuggestion());
- mScript.assertLatestPhoneSuggestion(phoneId, phoneSuggestion);
+ // Look inside and check what the strategy considers the current best telephony suggestion.
+ // It should still be the, it's just no longer used.
+ assertNull(mScript.peekBestTelephonySuggestion());
+ mScript.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
}
@Test
@@ -413,21 +413,21 @@
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
- int phoneId = ARBITRARY_PHONE_ID;
+ int slotIndex = ARBITRARY_SLOT_INDEX;
- // Simulate a phone suggestion.
+ // Simulate a telephony suggestion.
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- PhoneTimeSuggestion phoneTimeSuggestion =
- mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+ TelephonyTimeSuggestion telephonyTimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis);
// Simulate the passage of time.
mScript.simulateTimePassing();
long expectedAutoClockMillis =
- mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime());
- mScript.simulatePhoneTimeSuggestion(phoneTimeSuggestion)
+ mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUtcTime());
+ mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
- .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Simulate the passage of time.
mScript.simulateTimePassing();
@@ -435,7 +435,7 @@
// Switch to manual.
mScript.simulateAutoTimeDetectionToggle()
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Simulate the passage of time.
mScript.simulateTimePassing();
@@ -450,7 +450,7 @@
mScript.calculateTimeInMillisForNow(manualTimeSuggestion.getUtcTime());
mScript.simulateManualTimeSuggestion(manualTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedManualClockMillis)
- .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Simulate the passage of time.
mScript.simulateTimePassing();
@@ -459,14 +459,14 @@
mScript.simulateAutoTimeDetectionToggle();
expectedAutoClockMillis =
- mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUtcTime());
mScript.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
- .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Switch back to manual - nothing should happen to the clock.
mScript.simulateAutoTimeDetectionToggle()
.verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+ .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
}
/**
@@ -515,19 +515,19 @@
}
@Test
- public void testSuggestNetworkTime_phoneSuggestionsBeatNetworkSuggestions() {
+ public void testSuggestNetworkTime_telephonySuggestionsBeatNetworkSuggestions() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true);
// Three obviously different times that could not be mistaken for each other.
long networkTimeMillis1 = ARBITRARY_TEST_TIME_MILLIS;
long networkTimeMillis2 = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(30).toMillis();
- long phoneTimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(60).toMillis();
+ long telephonyTimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(60).toMillis();
// A small increment used to simulate the passage of time, but not enough to interfere with
// macro-level time changes associated with suggestion age.
final long smallTimeIncrementMillis = 101;
- // A network suggestion is made. It should be used because there is no phone suggestion.
+ // A network suggestion is made. It should be used because there is no telephony suggestion.
NetworkTimeSuggestion networkTimeSuggestion1 =
mScript.generateNetworkTimeSuggestion(networkTimeMillis1);
mScript.simulateTimePassing(smallTimeIncrementMillis)
@@ -536,37 +536,37 @@
mScript.calculateTimeInMillisForNow(networkTimeSuggestion1.getUtcTime()));
// Check internal state.
- mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, null)
+ mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, null)
.assertLatestNetworkSuggestion(networkTimeSuggestion1);
assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
- assertNull(mScript.peekBestPhoneSuggestion());
+ assertNull(mScript.peekBestTelephonySuggestion());
// Simulate a little time passing.
mScript.simulateTimePassing(smallTimeIncrementMillis)
.verifySystemClockWasNotSetAndResetCallTracking();
- // Now a phone suggestion is made. Phone suggestions are prioritized over network
+ // Now a telephony suggestion is made. Telephony suggestions are prioritized over network
// suggestions so it should "win".
- PhoneTimeSuggestion phoneTimeSuggestion =
- mScript.generatePhoneTimeSuggestion(ARBITRARY_PHONE_ID, phoneTimeMillis);
+ TelephonyTimeSuggestion telephonyTimeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeMillis);
mScript.simulateTimePassing(smallTimeIncrementMillis)
- .simulatePhoneTimeSuggestion(phoneTimeSuggestion)
+ .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUtcTime()));
// Check internal state.
- mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion1);
assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
- assertEquals(phoneTimeSuggestion, mScript.peekBestPhoneSuggestion());
+ assertEquals(telephonyTimeSuggestion, mScript.peekBestTelephonySuggestion());
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use".
mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2)
.verifySystemClockWasNotSetAndResetCallTracking();
- // Now another network suggestion is made. Phone suggestions are prioritized over network
- // suggestions so the latest phone suggestion should still "win".
+ // Now another network suggestion is made. Telephony suggestions are prioritized over
+ // network suggestions so the latest telephony suggestion should still "win".
NetworkTimeSuggestion networkTimeSuggestion2 =
mScript.generateNetworkTimeSuggestion(networkTimeMillis2);
mScript.simulateTimePassing(smallTimeIncrementMillis)
@@ -574,14 +574,14 @@
.verifySystemClockWasNotSetAndResetCallTracking();
// Check internal state.
- mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion2);
assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
- assertEquals(phoneTimeSuggestion, mScript.peekBestPhoneSuggestion());
+ assertEquals(telephonyTimeSuggestion, mScript.peekBestTelephonySuggestion());
// Simulate some significant time passing: half the time allowed before a time signal
- // becomes "too old to use". This should mean that phoneTimeSuggestion is now too old to be
- // used but networkTimeSuggestion2 is not.
+ // becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to
+ // be used but networkTimeSuggestion2 is not.
mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2);
// NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
@@ -591,10 +591,10 @@
mScript.verifySystemClockWasNotSetAndResetCallTracking();
// Check internal state.
- mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion2);
assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
- assertNull(mScript.peekBestPhoneSuggestion());
+ assertNull(mScript.peekBestTelephonySuggestion());
// Toggle auto-time off and on to force the detection logic to run.
mScript.simulateAutoTimeDetectionToggle()
@@ -606,10 +606,10 @@
mScript.calculateTimeInMillisForNow(networkTimeSuggestion2.getUtcTime()));
// Check internal state.
- mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion2);
assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
- assertNull(mScript.peekBestPhoneSuggestion());
+ assertNull(mScript.peekBestTelephonySuggestion());
}
/**
@@ -760,8 +760,8 @@
return mFakeCallback.peekSystemClockMillis();
}
- Script simulatePhoneTimeSuggestion(PhoneTimeSuggestion timeSuggestion) {
- mTimeDetectorStrategy.suggestPhoneTime(timeSuggestion);
+ Script simulateTelephonyTimeSuggestion(TelephonyTimeSuggestion timeSuggestion) {
+ mTimeDetectorStrategy.suggestTelephonyTime(timeSuggestion);
return this;
}
@@ -806,10 +806,10 @@
}
/**
- * White box test info: Asserts the latest suggestion for the phone ID is as expected.
+ * White box test info: Asserts the latest suggestion for the slotIndex is as expected.
*/
- Script assertLatestPhoneSuggestion(int phoneId, PhoneTimeSuggestion expected) {
- assertEquals(expected, mTimeDetectorStrategy.getLatestPhoneSuggestion(phoneId));
+ Script assertLatestTelephonySuggestion(int slotIndex, TelephonyTimeSuggestion expected) {
+ assertEquals(expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex));
return this;
}
@@ -822,11 +822,11 @@
}
/**
- * White box test info: Returns the phone suggestion that would be used, if any, given the
- * current elapsed real time clock and regardless of origin prioritization.
+ * White box test info: Returns the telephony suggestion that would be used, if any, given
+ * the current elapsed real time clock and regardless of origin prioritization.
*/
- PhoneTimeSuggestion peekBestPhoneSuggestion() {
- return mTimeDetectorStrategy.findBestPhoneSuggestionForTests();
+ TelephonyTimeSuggestion peekBestTelephonySuggestion() {
+ return mTimeDetectorStrategy.findBestTelephonySuggestionForTests();
}
/**
@@ -848,15 +848,15 @@
}
/**
- * Generates a PhoneTimeSuggestion using the current elapsed realtime clock for the
- * reference time.
+ * Generates a {@link TelephonyTimeSuggestion} using the current elapsed realtime clock for
+ * the reference time.
*/
- PhoneTimeSuggestion generatePhoneTimeSuggestion(int phoneId, Long timeMillis) {
+ TelephonyTimeSuggestion generateTelephonyTimeSuggestion(int slotIndex, Long timeMillis) {
TimestampedValue<Long> time = null;
if (timeMillis != null) {
time = new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis);
}
- return createPhoneTimeSuggestion(phoneId, time);
+ return createTelephonyTimeSuggestion(slotIndex, time);
}
/**
@@ -878,9 +878,9 @@
}
}
- private static PhoneTimeSuggestion createPhoneTimeSuggestion(int phoneId,
+ private static TelephonyTimeSuggestion createTelephonyTimeSuggestion(int slotIndex,
TimestampedValue<Long> utcTime) {
- return new PhoneTimeSuggestion.Builder(phoneId)
+ return new TelephonyTimeSuggestion.Builder(slotIndex)
.setUtcTime(utcTime)
.build();
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
index 3e7d40a..039c2b4 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -29,7 +29,7 @@
import static org.mockito.Mockito.when;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.HandlerThread;
@@ -76,35 +76,35 @@
}
@Test(expected = SecurityException.class)
- public void testSuggestPhoneTime_withoutPermission() {
+ public void testSuggestTelephonyTime_withoutPermission() {
doThrow(new SecurityException("Mock"))
.when(mMockContext).enforceCallingPermission(anyString(), any());
- PhoneTimeZoneSuggestion timeZoneSuggestion = createPhoneTimeZoneSuggestion();
+ TelephonyTimeZoneSuggestion timeZoneSuggestion = createTelephonyTimeZoneSuggestion();
try {
- mTimeZoneDetectorService.suggestPhoneTimeZone(timeZoneSuggestion);
+ mTimeZoneDetectorService.suggestTelephonyTimeZone(timeZoneSuggestion);
fail();
} finally {
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE),
+ eq(android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE),
anyString());
}
}
@Test
- public void testSuggestPhoneTimeZone() throws Exception {
+ public void testSuggestTelephonyTimeZone() throws Exception {
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
- PhoneTimeZoneSuggestion timeZoneSuggestion = createPhoneTimeZoneSuggestion();
- mTimeZoneDetectorService.suggestPhoneTimeZone(timeZoneSuggestion);
+ TelephonyTimeZoneSuggestion timeZoneSuggestion = createTelephonyTimeZoneSuggestion();
+ mTimeZoneDetectorService.suggestTelephonyTimeZone(timeZoneSuggestion);
mTestHandler.assertTotalMessagesEnqueued(1);
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE),
+ eq(android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE),
anyString());
mTestHandler.waitForMessagesToBeProcessed();
- mStubbedTimeZoneDetectorStrategy.verifySuggestPhoneTimeZoneCalled(timeZoneSuggestion);
+ mStubbedTimeZoneDetectorStrategy.verifySuggestTelephonyTimeZoneCalled(timeZoneSuggestion);
}
@Test(expected = SecurityException.class)
@@ -165,12 +165,12 @@
mStubbedTimeZoneDetectorStrategy.verifyHandleAutoTimeZoneDetectionChangedCalled();
}
- private static PhoneTimeZoneSuggestion createPhoneTimeZoneSuggestion() {
+ private static TelephonyTimeZoneSuggestion createTelephonyTimeZoneSuggestion() {
int slotIndex = 1234;
- return new PhoneTimeZoneSuggestion.Builder(slotIndex)
+ return new TelephonyTimeZoneSuggestion.Builder(slotIndex)
.setZoneId("TestZoneId")
- .setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
- .setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE)
+ .setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
+ .setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE)
.build();
}
@@ -181,14 +181,14 @@
private static class StubbedTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
// Call tracking.
- private PhoneTimeZoneSuggestion mLastPhoneSuggestion;
+ private TelephonyTimeZoneSuggestion mLastTelephonySuggestion;
private ManualTimeZoneSuggestion mLastManualSuggestion;
private boolean mHandleAutoTimeZoneDetectionChangedCalled;
private boolean mDumpCalled;
@Override
- public void suggestPhoneTimeZone(PhoneTimeZoneSuggestion timeZoneSuggestion) {
- mLastPhoneSuggestion = timeZoneSuggestion;
+ public void suggestTelephonyTimeZone(TelephonyTimeZoneSuggestion timeZoneSuggestion) {
+ mLastTelephonySuggestion = timeZoneSuggestion;
}
@Override
@@ -207,14 +207,14 @@
}
void resetCallTracking() {
- mLastPhoneSuggestion = null;
+ mLastTelephonySuggestion = null;
mLastManualSuggestion = null;
mHandleAutoTimeZoneDetectionChangedCalled = false;
mDumpCalled = false;
}
- void verifySuggestPhoneTimeZoneCalled(PhoneTimeZoneSuggestion expectedSuggestion) {
- assertEquals(expectedSuggestion, mLastPhoneSuggestion);
+ void verifySuggestTelephonyTimeZoneCalled(TelephonyTimeZoneSuggestion expectedSuggestion) {
+ assertEquals(expectedSuggestion, mLastTelephonySuggestion);
}
public void verifySuggestManualTimeZoneCalled(ManualTimeZoneSuggestion expectedSuggestion) {
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index 1e38711..ba30967 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -16,20 +16,20 @@
package com.android.server.timezonedetector;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
-import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
-import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.PHONE_SCORE_HIGH;
-import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.PHONE_SCORE_HIGHEST;
-import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.PHONE_SCORE_LOW;
-import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.PHONE_SCORE_MEDIUM;
-import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.PHONE_SCORE_NONE;
-import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.PHONE_SCORE_USAGE_THRESHOLD;
+import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_HIGH;
+import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_HIGHEST;
+import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_LOW;
+import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_MEDIUM;
+import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_NONE;
+import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_USAGE_THRESHOLD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -37,11 +37,11 @@
import static org.junit.Assert.assertTrue;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion.MatchType;
-import android.app.timezonedetector.PhoneTimeZoneSuggestion.Quality;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion.MatchType;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion.Quality;
-import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.QualifiedPhoneTimeZoneSuggestion;
+import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.QualifiedTelephonyTimeZoneSuggestion;
import org.junit.Before;
import org.junit.Test;
@@ -58,24 +58,24 @@
/** A time zone used for initialization that does not occur elsewhere in tests. */
private static final String ARBITRARY_TIME_ZONE_ID = "Etc/UTC";
- private static final int PHONE1_ID = 10000;
- private static final int PHONE2_ID = 20000;
+ private static final int SLOT_INDEX1 = 10000;
+ private static final int SLOT_INDEX2 = 20000;
// Suggestion test cases are ordered so that each successive one is of the same or higher score
// than the previous.
private static final SuggestionTestCase[] TEST_CASES = new SuggestionTestCase[] {
newTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY,
- QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS, PHONE_SCORE_LOW),
+ QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS, TELEPHONY_SCORE_LOW),
newTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY, QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
- PHONE_SCORE_MEDIUM),
+ TELEPHONY_SCORE_MEDIUM),
newTestCase(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET,
- QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, PHONE_SCORE_MEDIUM),
- newTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY, QUALITY_SINGLE_ZONE, PHONE_SCORE_HIGH),
+ QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, TELEPHONY_SCORE_MEDIUM),
+ newTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY, QUALITY_SINGLE_ZONE, TELEPHONY_SCORE_HIGH),
newTestCase(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE,
- PHONE_SCORE_HIGH),
+ TELEPHONY_SCORE_HIGH),
newTestCase(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY,
- QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, PHONE_SCORE_HIGHEST),
- newTestCase(MATCH_TYPE_EMULATOR_ZONE_ID, QUALITY_SINGLE_ZONE, PHONE_SCORE_HIGHEST),
+ QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, TELEPHONY_SCORE_HIGHEST),
+ newTestCase(MATCH_TYPE_EMULATOR_ZONE_ID, QUALITY_SINGLE_ZONE, TELEPHONY_SCORE_HIGHEST),
};
private TimeZoneDetectorStrategyImpl mTimeZoneDetectorStrategy;
@@ -89,76 +89,82 @@
}
@Test
- public void testEmptyPhoneSuggestions() {
- PhoneTimeZoneSuggestion phone1TimeZoneSuggestion = createEmptyPhone1Suggestion();
- PhoneTimeZoneSuggestion phone2TimeZoneSuggestion = createEmptyPhone2Suggestion();
+ public void testEmptyTelephonySuggestions() {
+ TelephonyTimeZoneSuggestion slotIndex1TimeZoneSuggestion =
+ createEmptySlotIndex1Suggestion();
+ TelephonyTimeZoneSuggestion slotIndex2TimeZoneSuggestion =
+ createEmptySlotIndex2Suggestion();
Script script = new Script()
.initializeAutoTimeZoneDetection(true)
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
- script.suggestPhoneTimeZone(phone1TimeZoneSuggestion)
+ script.suggestTelephonyTimeZone(slotIndex1TimeZoneSuggestion)
.verifyTimeZoneNotSet();
// Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedPhone1ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(phone1TimeZoneSuggestion, PHONE_SCORE_NONE);
- assertEquals(expectedPhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
- assertNull(mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE2_ID));
- assertEquals(expectedPhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ QualifiedTelephonyTimeZoneSuggestion expectedSlotIndex1ScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(slotIndex1TimeZoneSuggestion,
+ TELEPHONY_SCORE_NONE);
+ assertEquals(expectedSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertNull(mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX2));
+ assertEquals(expectedSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
- script.suggestPhoneTimeZone(phone2TimeZoneSuggestion)
+ script.suggestTelephonyTimeZone(slotIndex2TimeZoneSuggestion)
.verifyTimeZoneNotSet();
// Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedPhone2ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(phone2TimeZoneSuggestion, PHONE_SCORE_NONE);
- assertEquals(expectedPhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedPhone2ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE2_ID));
- // Phone 1 should always beat phone 2, all other things being equal.
- assertEquals(expectedPhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ QualifiedTelephonyTimeZoneSuggestion expectedSlotIndex2ScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(slotIndex2TimeZoneSuggestion,
+ TELEPHONY_SCORE_NONE);
+ assertEquals(expectedSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedSlotIndex2ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX2));
+ // SlotIndex1 should always beat slotIndex2, all other things being equal.
+ assertEquals(expectedSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
}
@Test
- public void testFirstPlausiblePhoneSuggestionAcceptedWhenTimeZoneUninitialized() {
+ public void testFirstPlausibleTelephonySuggestionAcceptedWhenTimeZoneUninitialized() {
SuggestionTestCase testCase = newTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY,
- QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS, PHONE_SCORE_LOW);
- PhoneTimeZoneSuggestion lowQualitySuggestion =
- testCase.createSuggestion(PHONE1_ID, "America/New_York");
+ QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS, TELEPHONY_SCORE_LOW);
+ TelephonyTimeZoneSuggestion lowQualitySuggestion =
+ testCase.createSuggestion(SLOT_INDEX1, "America/New_York");
// The device time zone setting is left uninitialized.
Script script = new Script()
.initializeAutoTimeZoneDetection(true);
// The very first suggestion will be taken.
- script.suggestPhoneTimeZone(lowQualitySuggestion)
+ script.suggestTelephonyTimeZone(lowQualitySuggestion)
.verifyTimeZoneSetAndReset(lowQualitySuggestion);
// Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(lowQualitySuggestion, testCase.expectedScore);
+ QualifiedTelephonyTimeZoneSuggestion expectedScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(
+ lowQualitySuggestion, testCase.expectedScore);
assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
// Another low quality suggestion will be ignored now that the setting is initialized.
- PhoneTimeZoneSuggestion lowQualitySuggestion2 =
- testCase.createSuggestion(PHONE1_ID, "America/Los_Angeles");
- script.suggestPhoneTimeZone(lowQualitySuggestion2)
+ TelephonyTimeZoneSuggestion lowQualitySuggestion2 =
+ testCase.createSuggestion(SLOT_INDEX1, "America/Los_Angeles");
+ script.suggestTelephonyTimeZone(lowQualitySuggestion2)
.verifyTimeZoneNotSet();
// Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedScoredSuggestion2 =
- new QualifiedPhoneTimeZoneSuggestion(lowQualitySuggestion2, testCase.expectedScore);
+ QualifiedTelephonyTimeZoneSuggestion expectedScoredSuggestion2 =
+ new QualifiedTelephonyTimeZoneSuggestion(
+ lowQualitySuggestion2, testCase.expectedScore);
assertEquals(expectedScoredSuggestion2,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
assertEquals(expectedScoredSuggestion2,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
}
/**
@@ -174,28 +180,28 @@
script.initializeAutoTimeZoneDetection(false)
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
- PhoneTimeZoneSuggestion suggestion =
- testCase.createSuggestion(PHONE1_ID, "Europe/London");
- script.suggestPhoneTimeZone(suggestion);
+ TelephonyTimeZoneSuggestion suggestion =
+ testCase.createSuggestion(SLOT_INDEX1, "Europe/London");
+ script.suggestTelephonyTimeZone(suggestion);
// When time zone detection is not enabled, the time zone suggestion will not be set
// regardless of the score.
script.verifyTimeZoneNotSet();
// Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(suggestion, testCase.expectedScore);
+ QualifiedTelephonyTimeZoneSuggestion expectedScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(suggestion, testCase.expectedScore);
assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
// Toggling the time zone setting on should cause the device setting to be set.
script.autoTimeZoneDetectionEnabled(true);
// When time zone detection is already enabled the suggestion (if it scores highly
// enough) should be set immediately.
- if (testCase.expectedScore >= PHONE_SCORE_USAGE_THRESHOLD) {
+ if (testCase.expectedScore >= TELEPHONY_SCORE_USAGE_THRESHOLD) {
script.verifyTimeZoneSetAndReset(suggestion);
} else {
script.verifyTimeZoneNotSet();
@@ -203,9 +209,9 @@
// Assert internal service state.
assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
// Toggling the time zone setting should off should do nothing.
script.autoTimeZoneDetectionEnabled(false)
@@ -213,20 +219,20 @@
// Assert internal service state.
assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
}
}
@Test
- public void testPhoneSuggestionsSinglePhone() {
+ public void testTelephonySuggestionsSingleSlotId() {
Script script = new Script()
.initializeAutoTimeZoneDetection(true)
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
for (SuggestionTestCase testCase : TEST_CASES) {
- makePhone1SuggestionAndCheckState(script, testCase);
+ makeSlotIndex1SuggestionAndCheckState(script, testCase);
}
/*
@@ -241,125 +247,128 @@
Collections.reverse(descendingCasesByScore);
for (SuggestionTestCase testCase : descendingCasesByScore) {
- makePhone1SuggestionAndCheckState(script, testCase);
+ makeSlotIndex1SuggestionAndCheckState(script, testCase);
}
}
- private void makePhone1SuggestionAndCheckState(Script script, SuggestionTestCase testCase) {
+ private void makeSlotIndex1SuggestionAndCheckState(Script script, SuggestionTestCase testCase) {
// Give the next suggestion a different zone from the currently set device time zone;
String currentZoneId = mFakeTimeZoneDetectorStrategyCallback.getDeviceTimeZone();
String suggestionZoneId =
"Europe/London".equals(currentZoneId) ? "Europe/Paris" : "Europe/London";
- PhoneTimeZoneSuggestion zonePhone1Suggestion =
- testCase.createSuggestion(PHONE1_ID, suggestionZoneId);
- QualifiedPhoneTimeZoneSuggestion expectedZonePhone1ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(zonePhone1Suggestion, testCase.expectedScore);
+ TelephonyTimeZoneSuggestion zoneSlotIndex1Suggestion =
+ testCase.createSuggestion(SLOT_INDEX1, suggestionZoneId);
+ QualifiedTelephonyTimeZoneSuggestion expectedZoneSlotIndex1ScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(
+ zoneSlotIndex1Suggestion, testCase.expectedScore);
- script.suggestPhoneTimeZone(zonePhone1Suggestion);
- if (testCase.expectedScore >= PHONE_SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(zonePhone1Suggestion);
+ script.suggestTelephonyTimeZone(zoneSlotIndex1Suggestion);
+ if (testCase.expectedScore >= TELEPHONY_SCORE_USAGE_THRESHOLD) {
+ script.verifyTimeZoneSetAndReset(zoneSlotIndex1Suggestion);
} else {
script.verifyTimeZoneNotSet();
}
// Assert internal service state.
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ assertEquals(expectedZoneSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedZoneSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
}
/**
- * Tries a set of test cases to see if the phone with the lowest ID is given preference. This
- * test also confirms that the time zone setting would only be set if a suggestion is of
- * sufficient quality.
+ * Tries a set of test cases to see if the slotIndex with the lowest numeric value is given
+ * preference. This test also confirms that the time zone setting would only be set if a
+ * suggestion is of sufficient quality.
*/
@Test
- public void testMultiplePhoneSuggestionScoringAndPhoneIdBias() {
+ public void testMultipleSlotIndexSuggestionScoringAndSlotIndexBias() {
String[] zoneIds = { "Europe/London", "Europe/Paris" };
- PhoneTimeZoneSuggestion emptyPhone1Suggestion = createEmptyPhone1Suggestion();
- PhoneTimeZoneSuggestion emptyPhone2Suggestion = createEmptyPhone2Suggestion();
- QualifiedPhoneTimeZoneSuggestion expectedEmptyPhone1ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(emptyPhone1Suggestion, PHONE_SCORE_NONE);
- QualifiedPhoneTimeZoneSuggestion expectedEmptyPhone2ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(emptyPhone2Suggestion, PHONE_SCORE_NONE);
+ TelephonyTimeZoneSuggestion emptySlotIndex1Suggestion = createEmptySlotIndex1Suggestion();
+ TelephonyTimeZoneSuggestion emptySlotIndex2Suggestion = createEmptySlotIndex2Suggestion();
+ QualifiedTelephonyTimeZoneSuggestion expectedEmptySlotIndex1ScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(emptySlotIndex1Suggestion,
+ TELEPHONY_SCORE_NONE);
+ QualifiedTelephonyTimeZoneSuggestion expectedEmptySlotIndex2ScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(emptySlotIndex2Suggestion,
+ TELEPHONY_SCORE_NONE);
Script script = new Script()
.initializeAutoTimeZoneDetection(true)
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
// Initialize the latest suggestions as empty so we don't need to worry about nulls
// below for the first loop.
- .suggestPhoneTimeZone(emptyPhone1Suggestion)
- .suggestPhoneTimeZone(emptyPhone2Suggestion)
+ .suggestTelephonyTimeZone(emptySlotIndex1Suggestion)
+ .suggestTelephonyTimeZone(emptySlotIndex2Suggestion)
.resetState();
for (SuggestionTestCase testCase : TEST_CASES) {
- PhoneTimeZoneSuggestion zonePhone1Suggestion =
- testCase.createSuggestion(PHONE1_ID, zoneIds[0]);
- PhoneTimeZoneSuggestion zonePhone2Suggestion =
- testCase.createSuggestion(PHONE2_ID, zoneIds[1]);
- QualifiedPhoneTimeZoneSuggestion expectedZonePhone1ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(zonePhone1Suggestion,
+ TelephonyTimeZoneSuggestion zoneSlotIndex1Suggestion =
+ testCase.createSuggestion(SLOT_INDEX1, zoneIds[0]);
+ TelephonyTimeZoneSuggestion zoneSlotIndex2Suggestion =
+ testCase.createSuggestion(SLOT_INDEX2, zoneIds[1]);
+ QualifiedTelephonyTimeZoneSuggestion expectedZoneSlotIndex1ScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(zoneSlotIndex1Suggestion,
testCase.expectedScore);
- QualifiedPhoneTimeZoneSuggestion expectedZonePhone2ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(zonePhone2Suggestion,
+ QualifiedTelephonyTimeZoneSuggestion expectedZoneSlotIndex2ScoredSuggestion =
+ new QualifiedTelephonyTimeZoneSuggestion(zoneSlotIndex2Suggestion,
testCase.expectedScore);
- // Start the test by making a suggestion for phone 1.
- script.suggestPhoneTimeZone(zonePhone1Suggestion);
- if (testCase.expectedScore >= PHONE_SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(zonePhone1Suggestion);
+ // Start the test by making a suggestion for slotIndex1.
+ script.suggestTelephonyTimeZone(zoneSlotIndex1Suggestion);
+ if (testCase.expectedScore >= TELEPHONY_SCORE_USAGE_THRESHOLD) {
+ script.verifyTimeZoneSetAndReset(zoneSlotIndex1Suggestion);
} else {
script.verifyTimeZoneNotSet();
}
// Assert internal service state.
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedEmptyPhone2ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE2_ID));
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ assertEquals(expectedZoneSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedEmptySlotIndex2ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX2));
+ assertEquals(expectedZoneSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
- // Phone 2 then makes an alternative suggestion with an identical score. Phone 1's
+ // SlotIndex2 then makes an alternative suggestion with an identical score. SlotIndex1's
// suggestion should still "win" if it is above the required threshold.
- script.suggestPhoneTimeZone(zonePhone2Suggestion);
+ script.suggestTelephonyTimeZone(zoneSlotIndex2Suggestion);
script.verifyTimeZoneNotSet();
// Assert internal service state.
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedZonePhone2ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE2_ID));
- // Phone 1 should always beat phone 2, all other things being equal.
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ assertEquals(expectedZoneSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedZoneSlotIndex2ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX2));
+ // SlotIndex1 should always beat slotIndex2, all other things being equal.
+ assertEquals(expectedZoneSlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
- // Withdrawing phone 1's suggestion should leave phone 2 as the new winner. Since the
- // zoneId is different, the time zone setting should be updated if the score is high
+ // Withdrawing slotIndex1's suggestion should leave slotIndex2 as the new winner. Since
+ // the zoneId is different, the time zone setting should be updated if the score is high
// enough.
- script.suggestPhoneTimeZone(emptyPhone1Suggestion);
- if (testCase.expectedScore >= PHONE_SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(zonePhone2Suggestion);
+ script.suggestTelephonyTimeZone(emptySlotIndex1Suggestion);
+ if (testCase.expectedScore >= TELEPHONY_SCORE_USAGE_THRESHOLD) {
+ script.verifyTimeZoneSetAndReset(zoneSlotIndex2Suggestion);
} else {
script.verifyTimeZoneNotSet();
}
// Assert internal service state.
- assertEquals(expectedEmptyPhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedZonePhone2ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE2_ID));
- assertEquals(expectedZonePhone2ScoredSuggestion,
- mTimeZoneDetectorStrategy.findBestPhoneSuggestionForTests());
+ assertEquals(expectedEmptySlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedZoneSlotIndex2ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX2));
+ assertEquals(expectedZoneSlotIndex2ScoredSuggestion,
+ mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
// Reset the state for the next loop.
- script.suggestPhoneTimeZone(emptyPhone2Suggestion)
+ script.suggestTelephonyTimeZone(emptySlotIndex2Suggestion)
.verifyTimeZoneNotSet();
- assertEquals(expectedEmptyPhone1ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedEmptyPhone2ScoredSuggestion,
- mTimeZoneDetectorStrategy.getLatestPhoneSuggestion(PHONE2_ID));
+ assertEquals(expectedEmptySlotIndex1ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1));
+ assertEquals(expectedEmptySlotIndex2ScoredSuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX2));
}
}
@@ -375,21 +384,21 @@
SuggestionTestCase testCase =
newTestCase(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE,
- PHONE_SCORE_HIGH);
- PhoneTimeZoneSuggestion losAngelesSuggestion =
- testCase.createSuggestion(PHONE1_ID, "America/Los_Angeles");
- PhoneTimeZoneSuggestion newYorkSuggestion =
- testCase.createSuggestion(PHONE1_ID, "America/New_York");
+ TELEPHONY_SCORE_HIGH);
+ TelephonyTimeZoneSuggestion losAngelesSuggestion =
+ testCase.createSuggestion(SLOT_INDEX1, "America/Los_Angeles");
+ TelephonyTimeZoneSuggestion newYorkSuggestion =
+ testCase.createSuggestion(SLOT_INDEX1, "America/New_York");
// Initialization.
- script.suggestPhoneTimeZone(losAngelesSuggestion)
+ script.suggestTelephonyTimeZone(losAngelesSuggestion)
.verifyTimeZoneSetAndReset(losAngelesSuggestion);
// Suggest it again - it should not be set because it is already set.
- script.suggestPhoneTimeZone(losAngelesSuggestion)
+ script.suggestTelephonyTimeZone(losAngelesSuggestion)
.verifyTimeZoneNotSet();
// Toggling time zone detection should set the device time zone only if the current setting
- // value is different from the most recent phone suggestion.
+ // value is different from the most recent telephony suggestion.
script.autoTimeZoneDetectionEnabled(false)
.verifyTimeZoneNotSet()
.autoTimeZoneDetectionEnabled(true)
@@ -398,7 +407,7 @@
// Simulate a user turning auto detection off, a new suggestion being made while auto
// detection is off, and the user turning it on again.
script.autoTimeZoneDetectionEnabled(false)
- .suggestPhoneTimeZone(newYorkSuggestion)
+ .suggestTelephonyTimeZone(newYorkSuggestion)
.verifyTimeZoneNotSet();
// Latest suggestion should be used.
script.autoTimeZoneDetectionEnabled(true)
@@ -433,12 +442,12 @@
return new ManualTimeZoneSuggestion(zoneId);
}
- private static PhoneTimeZoneSuggestion createEmptyPhone1Suggestion() {
- return new PhoneTimeZoneSuggestion.Builder(PHONE1_ID).build();
+ private static TelephonyTimeZoneSuggestion createEmptySlotIndex1Suggestion() {
+ return new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX1).build();
}
- private static PhoneTimeZoneSuggestion createEmptyPhone2Suggestion() {
- return new PhoneTimeZoneSuggestion.Builder(PHONE2_ID).build();
+ private static TelephonyTimeZoneSuggestion createEmptySlotIndex2Suggestion() {
+ return new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX2).build();
}
static class FakeTimeZoneDetectorStrategyCallback
@@ -565,9 +574,11 @@
return this;
}
- /** Simulates the time zone detection strategy receiving a phone-originated suggestion. */
- Script suggestPhoneTimeZone(PhoneTimeZoneSuggestion phoneTimeZoneSuggestion) {
- mTimeZoneDetectorStrategy.suggestPhoneTimeZone(phoneTimeZoneSuggestion);
+ /**
+ * Simulates the time zone detection strategy receiving a telephony-originated suggestion.
+ */
+ Script suggestTelephonyTimeZone(TelephonyTimeZoneSuggestion timeZoneSuggestion) {
+ mTimeZoneDetectorStrategy.suggestTelephonyTimeZone(timeZoneSuggestion);
return this;
}
@@ -582,7 +593,7 @@
return this;
}
- Script verifyTimeZoneSetAndReset(PhoneTimeZoneSuggestion suggestion) {
+ Script verifyTimeZoneSetAndReset(TelephonyTimeZoneSuggestion suggestion) {
mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(suggestion.getZoneId());
mFakeTimeZoneDetectorStrategyCallback.commitAllChanges();
return this;
@@ -611,8 +622,8 @@
this.expectedScore = expectedScore;
}
- private PhoneTimeZoneSuggestion createSuggestion(int phoneId, String zoneId) {
- return new PhoneTimeZoneSuggestion.Builder(phoneId)
+ private TelephonyTimeZoneSuggestion createSuggestion(int slotIndex, String zoneId) {
+ return new TelephonyTimeZoneSuggestion.Builder(slotIndex)
.setZoneId(zoneId)
.setMatchType(matchType)
.setQuality(quality)
diff --git a/tests/BlobStoreTestUtils/Android.bp b/tests/BlobStoreTestUtils/Android.bp
new file mode 100644
index 0000000..edd2b43
--- /dev/null
+++ b/tests/BlobStoreTestUtils/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2020 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.
+
+java_library {
+ name: "BlobStoreTestUtils",
+ srcs: ["src/**/*.java"],
+ static_libs: ["truth-prebuilt"],
+ platform_apis: true
+}
\ No newline at end of file
diff --git a/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java b/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
new file mode 100644
index 0000000..f96766a
--- /dev/null
+++ b/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2020 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.utils.blob;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.blob.BlobHandle;
+import android.app.blob.BlobStoreManager;
+import android.content.Context;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.nio.file.Files;
+import java.security.MessageDigest;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+public class DummyBlobData {
+ private static final long DEFAULT_SIZE_BYTES = 10 * 1024L * 1024L;
+ private static final int BUFFER_SIZE_BYTES = 16 * 1024;
+
+ private final Context mContext;
+ private final Random mRandom;
+ private final File mFile;
+ private final long mFileSize;
+ private final String mLabel;
+
+ byte[] mFileDigest;
+ long mExpiryTimeMs;
+
+ public DummyBlobData(Context context) {
+ this(context, new Random(0), "blob_" + System.nanoTime());
+ }
+
+ public DummyBlobData(Context context, long fileSize) {
+ this(context, fileSize, new Random(0), "blob_" + System.nanoTime(), "Test label");
+ }
+
+ public DummyBlobData(Context context, Random random, String fileName) {
+ this(context, DEFAULT_SIZE_BYTES, random, fileName, "Test label");
+ }
+
+ public DummyBlobData(Context context, Random random, String fileName, String label) {
+ this(context, DEFAULT_SIZE_BYTES, random, fileName, label);
+ }
+
+ public DummyBlobData(Context context, long fileSize, Random random, String fileName,
+ String label) {
+ mContext = context;
+ mRandom = random;
+ mFile = new File(mContext.getFilesDir(), fileName);
+ mFileSize = fileSize;
+ mLabel = label;
+ }
+
+ public void prepare() throws Exception {
+ try (RandomAccessFile file = new RandomAccessFile(mFile, "rw")) {
+ writeRandomData(file, mFileSize);
+ }
+ mFileDigest = FileUtils.digest(mFile, "SHA-256");
+ mExpiryTimeMs = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1);
+ }
+
+ public BlobHandle getBlobHandle() throws Exception {
+ return BlobHandle.createWithSha256(createSha256Digest(mFile), mLabel,
+ mExpiryTimeMs, "test_tag");
+ }
+
+ public long getFileSize() throws Exception {
+ return mFileSize;
+ }
+
+ public long getExpiryTimeMillis() {
+ return mExpiryTimeMs;
+ }
+
+ public void delete() {
+ mFile.delete();
+ }
+
+ public void writeToSession(BlobStoreManager.Session session) throws Exception {
+ writeToSession(session, 0, mFileSize);
+ }
+
+ public void writeToSession(BlobStoreManager.Session session,
+ long offsetBytes, long lengthBytes) throws Exception {
+ try (FileInputStream in = new FileInputStream(mFile)) {
+ in.getChannel().position(offsetBytes);
+ try (FileOutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(
+ session.openWrite(offsetBytes, lengthBytes))) {
+ copy(in, out, lengthBytes);
+ }
+ }
+ }
+
+ public void writeToFd(FileDescriptor fd, long offsetBytes, long lengthBytes) throws Exception {
+ try (FileInputStream in = new FileInputStream(mFile)) {
+ in.getChannel().position(offsetBytes);
+ try (FileOutputStream out = new FileOutputStream(fd)) {
+ copy(in, out, lengthBytes);
+ }
+ }
+ }
+
+ private void copy(InputStream in, OutputStream out, long lengthBytes) throws Exception {
+ final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
+ long bytesWrittern = 0;
+ while (bytesWrittern < lengthBytes) {
+ final int toWrite = (bytesWrittern + buffer.length <= lengthBytes)
+ ? buffer.length : (int) (lengthBytes - bytesWrittern);
+ in.read(buffer, 0, toWrite);
+ out.write(buffer, 0, toWrite);
+ bytesWrittern += toWrite;
+ }
+ }
+
+ public void readFromSessionAndVerifyBytes(BlobStoreManager.Session session,
+ long offsetBytes, int lengthBytes) throws Exception {
+ final byte[] expectedBytes = new byte[lengthBytes];
+ try (FileInputStream in = new FileInputStream(mFile)) {
+ read(in, expectedBytes, offsetBytes, lengthBytes);
+ }
+
+ final byte[] actualBytes = new byte[lengthBytes];
+ try (FileInputStream in = new ParcelFileDescriptor.AutoCloseInputStream(
+ session.openWrite(0L, 0L))) {
+ read(in, actualBytes, offsetBytes, lengthBytes);
+ }
+
+ assertThat(actualBytes).isEqualTo(expectedBytes);
+
+ }
+
+ private void read(FileInputStream in, byte[] buffer,
+ long offsetBytes, int lengthBytes) throws Exception {
+ in.getChannel().position(offsetBytes);
+ in.read(buffer, 0, lengthBytes);
+ }
+
+ public void readFromSessionAndVerifyDigest(BlobStoreManager.Session session)
+ throws Exception {
+ readFromSessionAndVerifyDigest(session, 0, mFile.length());
+ }
+
+ public void readFromSessionAndVerifyDigest(BlobStoreManager.Session session,
+ long offsetBytes, long lengthBytes) throws Exception {
+ final byte[] actualDigest;
+ try (FileInputStream in = new ParcelFileDescriptor.AutoCloseInputStream(
+ session.openWrite(0L, 0L))) {
+ actualDigest = createSha256Digest(in, offsetBytes, lengthBytes);
+ }
+
+ assertThat(actualDigest).isEqualTo(mFileDigest);
+ }
+
+ public void verifyBlob(ParcelFileDescriptor pfd) throws Exception {
+ final byte[] actualDigest;
+ try (FileInputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
+ actualDigest = FileUtils.digest(in, "SHA-256");
+ }
+ assertThat(actualDigest).isEqualTo(mFileDigest);
+ }
+
+ private byte[] createSha256Digest(FileInputStream in, long offsetBytes, long lengthBytes)
+ throws Exception {
+ final MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ in.getChannel().position(offsetBytes);
+ final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
+ long bytesRead = 0;
+ while (bytesRead < lengthBytes) {
+ int toRead = (bytesRead + buffer.length <= lengthBytes)
+ ? buffer.length : (int) (lengthBytes - bytesRead);
+ toRead = in.read(buffer, 0, toRead);
+ digest.update(buffer, 0, toRead);
+ bytesRead += toRead;
+ }
+ return digest.digest();
+ }
+
+ private byte[] createSha256Digest(File file) throws Exception {
+ final MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ try (BufferedInputStream in = new BufferedInputStream(
+ Files.newInputStream(file.toPath()))) {
+ final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
+ int bytesRead;
+ while ((bytesRead = in.read(buffer)) > 0) {
+ digest.update(buffer, 0, bytesRead);
+ }
+ }
+ return digest.digest();
+ }
+
+ private void writeRandomData(RandomAccessFile file, long fileSize)
+ throws Exception {
+ long bytesWritten = 0;
+ final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
+ while (bytesWritten < fileSize) {
+ mRandom.nextBytes(buffer);
+ final int toWrite = (bytesWritten + buffer.length <= fileSize)
+ ? buffer.length : (int) (fileSize - bytesWritten);
+ file.seek(bytesWritten);
+ file.write(buffer, 0, toWrite);
+ bytesWritten += toWrite;
+ }
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b4f32e7..a0e98d0 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -6446,14 +6446,16 @@
public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
final NetworkRequest wifiRequest =
new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
-
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
- verify(mIBinder, timeout(TIMEOUT_MS))
- .linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
+ // Block until all other events are done processing.
+ HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
+ verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
+ verify(mConnectivityDiagnosticsCallback).asBinder();
assertTrue(
mService.mConnectivityDiagnosticsCallbacks.containsKey(
mConnectivityDiagnosticsCallback));
@@ -6476,8 +6478,10 @@
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
- verify(mIBinder, timeout(TIMEOUT_MS))
- .linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
+ // Block until all other events are done processing.
+ HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
+ verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
verify(mConnectivityDiagnosticsCallback).asBinder();
assertTrue(
mService.mConnectivityDiagnosticsCallbacks.containsKey(
@@ -6635,8 +6639,11 @@
public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception {
setUpConnectivityDiagnosticsCallback();
- // Wait for onConnectivityReport to fire
- verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
+ // Block until all other events are done processing.
+ HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
+ // Verify onConnectivityReport fired
+ verify(mConnectivityDiagnosticsCallback)
.onConnectivityReport(any(ConnectivityReport.class));
}
@@ -6648,9 +6655,11 @@
// cellular network agent
mCellNetworkAgent.notifyDataStallSuspected();
- // Wait for onDataStallSuspected to fire
- verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
- .onDataStallSuspected(any(DataStallReport.class));
+ // Block until all other events are done processing.
+ HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
+ // Verify onDataStallSuspected fired
+ verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(any(DataStallReport.class));
}
@Test
@@ -6661,15 +6670,21 @@
final boolean hasConnectivity = true;
mService.reportNetworkConnectivity(n, hasConnectivity);
- // Wait for onNetworkConnectivityReported to fire
- verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
+ // Block until all other events are done processing.
+ HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
+ // Verify onNetworkConnectivityReported fired
+ verify(mConnectivityDiagnosticsCallback)
.onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
final boolean noConnectivity = false;
mService.reportNetworkConnectivity(n, noConnectivity);
+ // Block until all other events are done processing.
+ HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
// Wait for onNetworkConnectivityReported to fire
- verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
+ verify(mConnectivityDiagnosticsCallback)
.onNetworkConnectivityReported(eq(n), eq(noConnectivity));
}
}