Merge "MediaRouter2: Add OnCreateSessionListener"
diff --git a/Android.bp b/Android.bp
index b3faef1..0e3d374 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1189,6 +1189,7 @@
"core/java/com/android/internal/util/Protocol.java",
"core/java/com/android/internal/util/Preconditions.java",
"telephony/java/android/telephony/Annotation.java",
+ ":net-utils-framework-wifi-common-srcs",
],
libs: [
"framework-annotations-lib",
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index 83195dc..0aa685d 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -25,9 +25,12 @@
import com.android.internal.infra.AndroidFuture;
import com.google.android.icing.proto.SchemaProto;
+import com.google.android.icing.proto.SearchResultProto;
+import com.google.android.icing.protobuf.InvalidProtocolBufferException;
import java.util.List;
import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
@@ -127,4 +130,94 @@
// TODO(b/147614371) Fix error report for multiple documents.
future.whenCompleteAsync((noop, err) -> callback.accept(err), executor);
}
+
+ /**
+ * This method searches for documents based on a given query string. It also accepts
+ * specifications regarding how to search and format the results.
+ *
+ *<p>Currently we support following features in the raw query format:
+ * <ul>
+ * <li>AND
+ * AND joins (e.g. “match documents that have both the terms ‘dog’ and
+ * ‘cat’”).
+ * Example: hello world matches documents that have both ‘hello’ and ‘world’
+ * <li>OR
+ * OR joins (e.g. “match documents that have either the term ‘dog’ or
+ * ‘cat’”).
+ * Example: dog OR puppy
+ * <li>Exclusion
+ * Exclude a term (e.g. “match documents that do
+ * not have the term ‘dog’”).
+ * Example: -dog excludes the term ‘dog’
+ * <li>Grouping terms
+ * Allow for conceptual grouping of subqueries to enable hierarchical structures (e.g.
+ * “match documents that have either ‘dog’ or ‘puppy’, and either ‘cat’ or ‘kitten’”).
+ * Example: (dog puppy) (cat kitten) two one group containing two terms.
+ * <li>Property restricts
+ * which properties of a document to specifically match terms in (e.g.
+ * “match documents where the ‘subject’ property contains ‘important’”).
+ * Example: subject:important matches documents with the term ‘important’ in the
+ * ‘subject’ property
+ * <li>Schema type restricts
+ * This is similar to property restricts, but allows for restricts on top-level document
+ * fields, such as schema_type. Clients should be able to limit their query to documents of
+ * a certain schema_type (e.g. “match documents that are of the ‘Email’ schema_type”).
+ * Example: { schema_type_filters: “Email”, “Video”,query: “dog” } will match documents
+ * that contain the query term ‘dog’ and are of either the ‘Email’ schema type or the
+ * ‘Video’ schema type.
+ * </ul>
+ *
+ * <p> It is strongly recommended to use Jetpack APIs.
+ *
+ * @param queryExpression Query String to search.
+ * @param searchSpec Spec for setting filters, raw query etc.
+ * @param executor Executor on which to invoke the callback.
+ * @param callback Callback to receive errors resulting from the query operation. If the
+ * operation succeeds, the callback will be invoked with {@code null}.
+ * @hide
+ */
+ @NonNull
+ public void query(
+ @NonNull String queryExpression,
+ @NonNull SearchSpec searchSpec,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull BiConsumer<? super SearchResults, ? super Throwable> callback) {
+ AndroidFuture<byte[]> future = new AndroidFuture<>();
+ future.whenCompleteAsync((searchResultBytes, err) -> {
+ if (err != null) {
+ callback.accept(null, err);
+ return;
+ }
+
+ if (searchResultBytes != null) {
+ SearchResultProto searchResultProto;
+ try {
+ searchResultProto = SearchResultProto.parseFrom(searchResultBytes);
+ } catch (InvalidProtocolBufferException e) {
+ callback.accept(null, e);
+ return;
+ }
+ if (searchResultProto.hasError()) {
+ // TODO(sidchhabra): Add better exception handling.
+ callback.accept(
+ null,
+ new RuntimeException(searchResultProto.getError().getErrorMessage()));
+ return;
+ }
+ SearchResults searchResults = new SearchResults(searchResultProto);
+ callback.accept(searchResults, null);
+ return;
+ }
+
+ // Nothing was supplied in the future at all
+ callback.accept(
+ null, new IllegalStateException("Unknown failure occurred while querying"));
+ }, executor);
+
+ try {
+ mService.query(queryExpression, searchSpec.getProto().toByteArray(), future);
+ } catch (RemoteException e) {
+ future.completeExceptionally(e);
+ }
+ }
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index fc83d8c..22250f4 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -1,5 +1,5 @@
/**
- * Copyright 2019, The Android Open Source Project
+ * 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.
@@ -29,4 +29,13 @@
*/
void setSchema(in byte[] schemaProto, in AndroidFuture callback);
void put(in byte[] documentBytes, in AndroidFuture callback);
+ /**
+ * Searches a document based on a given query string.
+ *
+ * @param queryExpression Query String to search.
+ * @param searchSpec Serialized SearchSpecProto.
+ * @param callback {@link AndroidFuture}. Will be completed with a serialized
+ * {@link SearchResultsProto}, or completed exceptionally if query fails.
+ */
+ void query(in String queryExpression, in byte[] searchSpecBytes, in AndroidFuture callback);
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IllegalSearchSpecException.java b/apex/appsearch/framework/java/android/app/appsearch/IllegalSearchSpecException.java
new file mode 100644
index 0000000..0d029f0
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/IllegalSearchSpecException.java
@@ -0,0 +1,36 @@
+/*
+ * 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 android.app.appsearch;
+
+import android.annotation.NonNull;
+
+/**
+ * Indicates that a {@link android.app.appsearch.SearchResults} has logical inconsistencies such
+ * as unpopulated mandatory fields or illegal combinations of parameters.
+ *
+ * @hide
+ */
+public class IllegalSearchSpecException extends IllegalArgumentException {
+ /**
+ * Constructs a new {@link IllegalSearchSpecException}.
+ *
+ * @param message A developer-readable description of the issue with the bundle.
+ */
+ public IllegalSearchSpecException(@NonNull String message) {
+ super(message);
+ }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
new file mode 100644
index 0000000..ec4258d
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
@@ -0,0 +1,89 @@
+/*
+ * 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 android.app.appsearch;
+
+import android.annotation.NonNull;
+
+import com.google.android.icing.proto.SearchResultProto;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * SearchResults are a list of results that are returned from a query. Each result from this
+ * list contains a document and may contain other fields like snippets based on request.
+ * @hide
+ */
+public final class SearchResults {
+
+ private final SearchResultProto mSearchResultProto;
+
+ /** @hide */
+ public SearchResults(SearchResultProto searchResultProto) {
+ mSearchResultProto = searchResultProto;
+ }
+
+ /**
+ * This class represents the result obtained from the query. It will contain the document which
+ * which matched the specified query string and specifications.
+ * @hide
+ */
+ public static final class Result {
+ private final SearchResultProto.ResultProto mResultProto;
+
+ private Result(SearchResultProto.ResultProto resultProto) {
+ mResultProto = resultProto;
+ }
+
+ /**
+ * Contains the matching {@link AppSearch.Document}.
+ * @return Document object which matched the query.
+ * @hide
+ */
+ // TODO(sidchhabra): Switch to Document constructor that takes proto.
+ @NonNull
+ public AppSearch.Document getDocument() {
+ return AppSearch.Document.newBuilder(mResultProto.getDocument().getUri(),
+ mResultProto.getDocument().getSchema())
+ .setCreationTimestampSecs(mResultProto.getDocument().getCreationTimestampSecs())
+ .setScore(mResultProto.getDocument().getScore())
+ .build();
+ }
+
+ // TODO(sidchhabra): Add Getter for ResultReader for Snippet.
+ }
+
+ @Override
+ public String toString() {
+ return mSearchResultProto.toString();
+ }
+
+ /**
+ * Returns a {@link Result} iterator. Returns Empty Iterator if there are no matching results.
+ * @hide
+ */
+ @NonNull
+ public Iterator<Result> getResults() {
+ List<Result> results = new ArrayList<>();
+ // TODO(sidchhabra): Pass results using a RemoteStream.
+ for (SearchResultProto.ResultProto resultProto : mSearchResultProto.getResultsList()) {
+ results.add(new Result(resultProto));
+ }
+ return results.iterator();
+ }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
new file mode 100644
index 0000000..5df7108
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
@@ -0,0 +1,127 @@
+/*
+ * 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 android.app.appsearch;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import com.google.android.icing.proto.SearchSpecProto;
+import com.google.android.icing.proto.TermMatchType;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class represents the specification logic for AppSearch. It can be used to set the type of
+ * search, like prefix or exact only or apply filters to search for a specific schema type only etc.
+ * @hide
+ *
+ */
+// TODO(sidchhabra) : AddResultSpec fields for Snippets etc.
+public final class SearchSpec {
+
+ private final SearchSpecProto mSearchSpecProto;
+
+ private SearchSpec(SearchSpecProto searchSpecProto) {
+ mSearchSpecProto = searchSpecProto;
+ }
+
+ /** Creates a new {@link SearchSpec.Builder}. */
+ @NonNull
+ public static SearchSpec.Builder newBuilder() {
+ return new SearchSpec.Builder();
+ }
+
+ /** @hide */
+ @NonNull
+ SearchSpecProto getProto() {
+ return mSearchSpecProto;
+ }
+
+ /** Term Match Type for the query. */
+ // NOTE: The integer values of these constants must match the proto enum constants in
+ // {@link com.google.android.icing.proto.SearchSpecProto.termMatchType}
+ @IntDef(prefix = {"TERM_MATCH_TYPE_"}, value = {
+ TERM_MATCH_TYPE_EXACT_ONLY,
+ TERM_MATCH_TYPE_PREFIX
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TermMatchTypeCode {}
+
+ public static final int TERM_MATCH_TYPE_EXACT_ONLY = 1;
+ public static final int TERM_MATCH_TYPE_PREFIX = 2;
+
+ /** Builder for {@link SearchSpec objects}. */
+ public static final class Builder {
+
+ private final SearchSpecProto.Builder mBuilder = SearchSpecProto.newBuilder();
+
+ private Builder(){}
+
+ /**
+ * Indicates how the query terms should match {@link TermMatchTypeCode} in the index.
+ *
+ * TermMatchType.Code=EXACT_ONLY
+ * Query terms will only match exact tokens in the index.
+ * Ex. A query term "foo" will only match indexed token "foo", and not "foot"
+ * or "football"
+ *
+ * TermMatchType.Code=PREFIX
+ * Query terms will match indexed tokens when the query term is a prefix of
+ * the token.
+ * Ex. A query term "foo" will match indexed tokens like "foo", "foot", and
+ * "football".
+ */
+ @NonNull
+ public Builder setTermMatchType(@TermMatchTypeCode int termMatchTypeCode) {
+ TermMatchType.Code termMatchTypeCodeProto =
+ TermMatchType.Code.forNumber(termMatchTypeCode);
+ if (termMatchTypeCodeProto == null) {
+ throw new IllegalArgumentException("Invalid term match type: " + termMatchTypeCode);
+ }
+ mBuilder.setTermMatchType(termMatchTypeCodeProto);
+ return this;
+ }
+
+ /**
+ * Adds a Schema type filter to {@link SearchSpec} Entry.
+ * Only search for documents that have the specified schema types.
+ * If unset, the query will search over all schema types.
+ */
+ @NonNull
+ public Builder setSchemaTypes(@NonNull String... schemaTypes) {
+ for (String schemaType : schemaTypes) {
+ mBuilder.addSchemaTypeFilters(schemaType);
+ }
+ return this;
+ }
+
+ /**
+ * Constructs a new {@link SearchSpec} from the contents of this builder.
+ *
+ * <p>After calling this method, the builder must no longer be used.
+ */
+ @NonNull
+ public SearchSpec build() {
+ if (mBuilder.getTermMatchType() == TermMatchType.Code.UNKNOWN) {
+ throw new IllegalSearchSpecException("Missing termMatchType field.");
+ }
+ return new SearchSpec(mBuilder.build());
+ }
+ }
+
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index ce7e04c..f63abd9 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -15,6 +15,7 @@
*/
package com.android.server.appsearch;
+import android.annotation.NonNull;
import android.app.appsearch.IAppSearchManager;
import android.content.Context;
import android.os.Binder;
@@ -24,9 +25,13 @@
import com.android.internal.util.Preconditions;
import com.android.server.SystemService;
import com.android.server.appsearch.impl.AppSearchImpl;
+import com.android.server.appsearch.impl.FakeIcing;
import com.android.server.appsearch.impl.ImplInstanceManager;
import com.google.android.icing.proto.SchemaProto;
+import com.google.android.icing.proto.SearchResultProto;
+import com.google.android.icing.proto.SearchSpecProto;
+import com.google.android.icing.protobuf.InvalidProtocolBufferException;
/**
* TODO(b/142567528): add comments when implement this class
@@ -35,8 +40,11 @@
public AppSearchManagerService(Context context) {
super(context);
+ mFakeIcing = new FakeIcing();
}
+ private final FakeIcing mFakeIcing;
+
@Override
public void onStart() {
publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
@@ -70,5 +78,22 @@
callback.completeExceptionally(t);
}
}
+ // TODO(sidchhabra):Init FakeIcing properly.
+ // TODO(sidchhabra): Do this in a threadpool.
+ @Override
+ public void query(@NonNull String queryExpression, @NonNull byte[] searchSpec,
+ AndroidFuture callback) {
+ Preconditions.checkNotNull(queryExpression);
+ Preconditions.checkNotNull(searchSpec);
+ SearchSpecProto searchSpecProto = null;
+ try {
+ searchSpecProto = SearchSpecProto.parseFrom(searchSpec);
+ } catch (InvalidProtocolBufferException e) {
+ throw new RuntimeException(e);
+ }
+ SearchResultProto searchResults =
+ mFakeIcing.query(queryExpression);
+ callback.complete(searchResults.toByteArray());
+ }
}
}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 8bc14d7..17573bb 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -24,11 +24,11 @@
import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static com.android.server.stats.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
-import static com.android.server.stats.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
-import static com.android.server.stats.ProcfsMemoryUtil.forEachPid;
-import static com.android.server.stats.ProcfsMemoryUtil.readCmdlineFromProcfs;
-import static com.android.server.stats.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
+import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
+import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
+import static com.android.server.stats.pull.ProcfsMemoryUtil.forEachPid;
+import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
+import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -135,8 +135,8 @@
import com.android.server.am.MemoryStatUtil.MemoryStat;
import com.android.server.notification.NotificationManagerService;
import com.android.server.role.RoleManagerInternal;
-import com.android.server.stats.IonMemoryUtil.IonAllocations;
-import com.android.server.stats.ProcfsMemoryUtil.MemorySnapshot;
+import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
+import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
import com.android.server.storage.DiskStatsFileLogger;
import com.android.server.storage.DiskStatsLoggingService;
@@ -722,207 +722,6 @@
pulledData.add(e);
}
- private void pullProcessMemoryState(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- List<ProcessMemoryState> processMemoryStates =
- LocalServices.getService(
- ActivityManagerInternal.class).getMemoryStateForProcesses();
- for (ProcessMemoryState processMemoryState : processMemoryStates) {
- final MemoryStat memoryStat = readMemoryStatFromFilesystem(processMemoryState.uid,
- processMemoryState.pid);
- if (memoryStat == null) {
- continue;
- }
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(processMemoryState.uid);
- e.writeString(processMemoryState.processName);
- e.writeInt(processMemoryState.oomScore);
- e.writeLong(memoryStat.pgfault);
- e.writeLong(memoryStat.pgmajfault);
- e.writeLong(memoryStat.rssInBytes);
- e.writeLong(memoryStat.cacheInBytes);
- e.writeLong(memoryStat.swapInBytes);
- e.writeLong(-1); // unused
- e.writeLong(-1); // unused
- e.writeInt(-1); // unsed
- pulledData.add(e);
- }
- }
-
- private void pullProcessMemoryHighWaterMark(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- List<ProcessMemoryState> managedProcessList =
- LocalServices.getService(
- ActivityManagerInternal.class).getMemoryStateForProcesses();
- for (ProcessMemoryState managedProcess : managedProcessList) {
- final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
- if (snapshot == null) {
- continue;
- }
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(managedProcess.uid);
- e.writeString(managedProcess.processName);
- // RSS high-water mark in bytes.
- e.writeLong((long) snapshot.rssHighWaterMarkInKilobytes * 1024L);
- e.writeInt(snapshot.rssHighWaterMarkInKilobytes);
- pulledData.add(e);
- }
- forEachPid((pid, cmdLine) -> {
- if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
- return;
- }
- final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
- if (snapshot == null) {
- return;
- }
- // Sometimes we get here a process that is not included in the whitelist. It comes
- // from forking the zygote for an app. We can ignore that sample because this process
- // is collected by ProcessMemoryState.
- if (isAppUid(snapshot.uid)) {
- return;
- }
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(snapshot.uid);
- e.writeString(cmdLine);
- // RSS high-water mark in bytes.
- e.writeLong((long) snapshot.rssHighWaterMarkInKilobytes * 1024L);
- e.writeInt(snapshot.rssHighWaterMarkInKilobytes);
- pulledData.add(e);
- });
- // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes.
- SystemProperties.set("sys.rss_hwm_reset.on", "1");
- }
-
- private void pullProcessMemorySnapshot(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- List<ProcessMemoryState> managedProcessList =
- LocalServices.getService(
- ActivityManagerInternal.class).getMemoryStateForProcesses();
- for (ProcessMemoryState managedProcess : managedProcessList) {
- final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
- if (snapshot == null) {
- continue;
- }
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(managedProcess.uid);
- e.writeString(managedProcess.processName);
- e.writeInt(managedProcess.pid);
- e.writeInt(managedProcess.oomScore);
- e.writeInt(snapshot.rssInKilobytes);
- e.writeInt(snapshot.anonRssInKilobytes);
- e.writeInt(snapshot.swapInKilobytes);
- e.writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes);
- pulledData.add(e);
- }
- forEachPid((pid, cmdLine) -> {
- if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
- return;
- }
- final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
- if (snapshot == null) {
- return;
- }
- // Sometimes we get here a process that is not included in the whitelist. It comes
- // from forking the zygote for an app. We can ignore that sample because this process
- // is collected by ProcessMemoryState.
- if (isAppUid(snapshot.uid)) {
- return;
- }
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(snapshot.uid);
- e.writeString(cmdLine);
- e.writeInt(pid);
- e.writeInt(-1001); // Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.
- e.writeInt(snapshot.rssInKilobytes);
- e.writeInt(snapshot.anonRssInKilobytes);
- e.writeInt(snapshot.swapInKilobytes);
- e.writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes);
- pulledData.add(e);
- });
- }
-
- private static boolean isAppUid(int uid) {
- return uid >= MIN_APP_UID;
- }
-
- private void pullSystemIonHeapSize(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- final long systemIonHeapSizeInBytes = readSystemIonHeapSizeFromDebugfs();
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeLong(systemIonHeapSizeInBytes);
- pulledData.add(e);
- }
-
- private void pullProcessSystemIonHeapSize(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- List<IonAllocations> result = readProcessSystemIonHeapSizesFromDebugfs();
- for (IonAllocations allocations : result) {
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(getUidForPid(allocations.pid));
- e.writeString(readCmdlineFromProcfs(allocations.pid));
- e.writeInt((int) (allocations.totalSizeInBytes / 1024));
- e.writeInt(allocations.count);
- e.writeInt((int) (allocations.maxSizeInBytes / 1024));
- pulledData.add(e);
- }
- }
-
- private void pullBinderCallsStats(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- BinderCallsStatsService.Internal binderStats =
- LocalServices.getService(BinderCallsStatsService.Internal.class);
- if (binderStats == null) {
- throw new IllegalStateException("binderStats is null");
- }
-
- List<ExportedCallStat> callStats = binderStats.getExportedCallStats();
- binderStats.reset();
- for (ExportedCallStat callStat : callStats) {
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(callStat.workSourceUid);
- e.writeString(callStat.className);
- e.writeString(callStat.methodName);
- e.writeLong(callStat.callCount);
- e.writeLong(callStat.exceptionCount);
- e.writeLong(callStat.latencyMicros);
- e.writeLong(callStat.maxLatencyMicros);
- e.writeLong(callStat.cpuTimeMicros);
- e.writeLong(callStat.maxCpuTimeMicros);
- e.writeLong(callStat.maxReplySizeBytes);
- e.writeLong(callStat.maxRequestSizeBytes);
- e.writeLong(callStat.recordedCallCount);
- e.writeInt(callStat.screenInteractive ? 1 : 0);
- e.writeInt(callStat.callingUid);
- pulledData.add(e);
- }
- }
-
- private void pullBinderCallsStatsExceptions(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- BinderCallsStatsService.Internal binderStats =
- LocalServices.getService(BinderCallsStatsService.Internal.class);
- if (binderStats == null) {
- throw new IllegalStateException("binderStats is null");
- }
-
- ArrayMap<String, Integer> exceptionStats = binderStats.getExportedExceptionStats();
- // TODO: decouple binder calls exceptions with the rest of the binder calls data so that we
- // can reset the exception stats.
- for (Entry<String, Integer> entry : exceptionStats.entrySet()) {
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeString(entry.getKey());
- e.writeInt(entry.getValue());
- pulledData.add(e);
- }
- }
-
private void pullLooperStats(int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
LooperStats looperStats = LocalServices.getService(LooperStats.class);
@@ -1397,49 +1196,6 @@
}
}
- private void pullTemperature(int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- long callingToken = Binder.clearCallingIdentity();
- try {
- List<Temperature> temperatures = sThermalService.getCurrentTemperatures();
- for (Temperature temp : temperatures) {
- StatsLogEventWrapper e =
- new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(temp.getType());
- e.writeString(temp.getName());
- e.writeInt((int) (temp.getValue() * 10));
- e.writeInt(temp.getStatus());
- pulledData.add(e);
- }
- } catch (RemoteException e) {
- // Should not happen.
- Slog.e(TAG, "Disconnected from thermal service. Cannot pull temperatures.");
- } finally {
- Binder.restoreCallingIdentity(callingToken);
- }
- }
-
- private void pullCoolingDevices(int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- long callingToken = Binder.clearCallingIdentity();
- try {
- List<CoolingDevice> devices = sThermalService.getCurrentCoolingDevices();
- for (CoolingDevice device : devices) {
- StatsLogEventWrapper e =
- new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(device.getType());
- e.writeString(device.getName());
- e.writeInt((int) (device.getValue()));
- pulledData.add(e);
- }
- } catch (RemoteException e) {
- // Should not happen.
- Slog.e(TAG, "Disconnected from thermal service. Cannot pull temperatures.");
- } finally {
- Binder.restoreCallingIdentity(callingToken);
- }
- }
-
private void pullDebugElapsedClock(int tagId,
long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
final long elapsedMillis = SystemClock.elapsedRealtime();
@@ -1823,41 +1579,6 @@
break;
}
- case StatsLog.PROCESS_MEMORY_STATE: {
- pullProcessMemoryState(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK: {
- pullProcessMemoryHighWaterMark(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.PROCESS_MEMORY_SNAPSHOT: {
- pullProcessMemorySnapshot(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.SYSTEM_ION_HEAP_SIZE: {
- pullSystemIonHeapSize(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE: {
- pullProcessSystemIonHeapSize(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.BINDER_CALLS: {
- pullBinderCallsStats(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.BINDER_CALLS_EXCEPTIONS: {
- pullBinderCallsStatsExceptions(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
case StatsLog.LOOPER_STATS: {
pullLooperStats(tagId, elapsedNanos, wallClockNanos, ret);
break;
@@ -1920,16 +1641,6 @@
break;
}
- case StatsLog.TEMPERATURE: {
- pullTemperature(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
- case StatsLog.COOLING_DEVICE: {
- pullCoolingDevices(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
case StatsLog.DEBUG_ELAPSED_CLOCK: {
pullDebugElapsedClock(tagId, elapsedNanos, wallClockNanos, ret);
break;
diff --git a/api/current.txt b/api/current.txt
index e27c318..d9c305a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -39750,8 +39750,8 @@
field public static final String EXTRA_INPUT_METHOD_ID = "input_method_id";
field public static final String EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME = "android.provider.extra.NOTIFICATION_LISTENER_COMPONENT_NAME";
field public static final String EXTRA_SUB_ID = "android.provider.extra.SUB_ID";
- field public static final String EXTRA_WIFI_CONFIGURATION_LIST = "android.provider.extra.WIFI_CONFIGURATION_LIST";
- field public static final String EXTRA_WIFI_CONFIGURATION_RESULT_LIST = "android.provider.extra.WIFI_CONFIGURATION_RESULT_LIST";
+ field public static final String EXTRA_WIFI_NETWORK_LIST = "android.provider.extra.WIFI_NETWORK_LIST";
+ field public static final String EXTRA_WIFI_NETWORK_RESULT_LIST = "android.provider.extra.WIFI_NETWORK_RESULT_LIST";
field public static final String INTENT_CATEGORY_USAGE_ACCESS_CONFIG = "android.intent.category.USAGE_ACCESS_CONFIG";
field public static final String METADATA_USAGE_ACCESS_REASON = "android.settings.metadata.USAGE_ACCESS_REASON";
}
@@ -55697,7 +55697,7 @@
method public int describeContents();
method @NonNull public android.os.Bundle getExtras();
method @NonNull public java.util.Collection<android.view.textclassifier.TextLinks.TextLink> getLinks();
- method @NonNull public String getText();
+ method @NonNull public CharSequence getText();
method public void writeToParcel(android.os.Parcel, int);
field public static final int APPLY_STRATEGY_IGNORE = 0; // 0x0
field public static final int APPLY_STRATEGY_REPLACE = 1; // 0x1
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 591d727..d5cda85 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -95,45 +95,6 @@
{{.atomTag = android::util::BATTERY_CYCLE_COUNT},
{.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}},
- // process_memory_state
- {{.atomTag = android::util::PROCESS_MEMORY_STATE},
- {.additiveFields = {4, 5, 6, 7, 8},
- .puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
-
- // process_memory_high_water_mark
- {{.atomTag = android::util::PROCESS_MEMORY_HIGH_WATER_MARK},
- {.puller =
- new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},
-
- // process_memory_snapshot
- {{.atomTag = android::util::PROCESS_MEMORY_SNAPSHOT},
- {.puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_SNAPSHOT)}},
-
- // system_ion_heap_size
- {{.atomTag = android::util::SYSTEM_ION_HEAP_SIZE},
- {.puller = new StatsCompanionServicePuller(android::util::SYSTEM_ION_HEAP_SIZE)}},
-
- // process_system_ion_heap_size
- {{.atomTag = android::util::PROCESS_SYSTEM_ION_HEAP_SIZE},
- {.puller = new StatsCompanionServicePuller(android::util::PROCESS_SYSTEM_ION_HEAP_SIZE)}},
-
- // temperature
- {{.atomTag = android::util::TEMPERATURE},
- {.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
-
- // cooling_device
- {{.atomTag = android::util::COOLING_DEVICE},
- {.puller = new StatsCompanionServicePuller(android::util::COOLING_DEVICE)}},
-
- // binder_calls
- {{.atomTag = android::util::BINDER_CALLS},
- {.additiveFields = {4, 5, 6, 8, 12},
- .puller = new StatsCompanionServicePuller(android::util::BINDER_CALLS)}},
-
- // binder_calls_exceptions
- {{.atomTag = android::util::BINDER_CALLS_EXCEPTIONS},
- {.puller = new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
-
// looper_stats
{{.atomTag = android::util::LOOPER_STATS},
{.additiveFields = {5, 6, 7, 8, 9},
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index d23754e..7ab85a4 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -1208,8 +1208,7 @@
WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
ResourcesImpl r = weakImplRef != null ? weakImplRef.get() : null;
if (r != null) {
- applyConfigurationToResourcesLocked(config, compat, tmpConfig,
- defaultDisplayMetrics, key, r);
+ applyConfigurationToResourcesLocked(config, compat, tmpConfig, key, r);
} else {
mResourceImpls.removeAt(i);
}
@@ -1224,8 +1223,7 @@
}
applyConfigurationToResourcesLocked(config, compat, tmpConfig,
- defaultDisplayMetrics, resourcesWithLoaders.resourcesKey(),
- resources.getImpl());
+ resourcesWithLoaders.resourcesKey(), resources.getImpl());
}
return changes != 0;
@@ -1236,40 +1234,33 @@
private void applyConfigurationToResourcesLocked(@NonNull Configuration config,
@Nullable CompatibilityInfo compat, Configuration tmpConfig,
- DisplayMetrics defaultDisplayMetrics, ResourcesKey key, ResourcesImpl resourcesImpl) {
+ ResourcesKey key, ResourcesImpl resourcesImpl) {
if (DEBUG || DEBUG_CONFIGURATION) {
Slog.v(TAG, "Changing resources "
+ resourcesImpl + " config to: " + config);
}
int displayId = key.mDisplayId;
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- DisplayMetrics dm = defaultDisplayMetrics;
final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
- if (!isDefaultDisplay || hasOverrideConfiguration) {
- tmpConfig.setTo(config);
+ tmpConfig.setTo(config);
- // Get new DisplayMetrics based on the DisplayAdjustments given
- // to the ResourcesImpl. Update a copy if the CompatibilityInfo
- // changed, because the ResourcesImpl object will handle the
- // update internally.
- DisplayAdjustments daj = resourcesImpl.getDisplayAdjustments();
- if (compat != null) {
- daj = new DisplayAdjustments(daj);
- daj.setCompatibilityInfo(compat);
- }
- dm = getDisplayMetrics(displayId, daj);
-
- if (!isDefaultDisplay) {
- applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
- }
-
- if (hasOverrideConfiguration) {
- tmpConfig.updateFrom(key.mOverrideConfiguration);
- }
- resourcesImpl.updateConfiguration(tmpConfig, dm, compat);
- } else {
- resourcesImpl.updateConfiguration(config, dm, compat);
+ // Get new DisplayMetrics based on the DisplayAdjustments given to the ResourcesImpl. Update
+ // a copy if the CompatibilityInfo changed, because the ResourcesImpl object will handle the
+ // update internally.
+ DisplayAdjustments daj = resourcesImpl.getDisplayAdjustments();
+ if (compat != null) {
+ daj = new DisplayAdjustments(daj);
+ daj.setCompatibilityInfo(compat);
}
+ daj.setConfiguration(config);
+ DisplayMetrics dm = getDisplayMetrics(displayId, daj);
+ if (displayId != Display.DEFAULT_DISPLAY) {
+ applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
+ }
+
+ if (hasOverrideConfiguration) {
+ tmpConfig.updateFrom(key.mOverrideConfiguration);
+ }
+ resourcesImpl.updateConfiguration(tmpConfig, dm, compat);
}
/**
diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
index 6df92a7..a34be5c 100644
--- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java
+++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
@@ -75,9 +75,15 @@
mLifecycleSequence.clear();
if (finish >= start) {
- // just go there
- for (int i = start + 1; i <= finish; i++) {
- mLifecycleSequence.add(i);
+ if (start == ON_START && finish == ON_STOP) {
+ // A case when we from start to stop state soon, we don't need to go
+ // through the resumed, paused state.
+ mLifecycleSequence.add(ON_STOP);
+ } else {
+ // just go there
+ for (int i = start + 1; i <= finish; i++) {
+ mLifecycleSequence.add(i);
+ }
}
} else { // finish < start, can't just cycle down
if (start == ON_PAUSE && finish == ON_RESUME) {
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 799dff9..fb5f136 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -26,6 +26,7 @@
import android.app.KeyguardManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Point;
import android.media.projection.MediaProjection;
import android.os.Handler;
@@ -400,10 +401,10 @@
if (display == null) {
// TODO: We cannot currently provide any override configurations for metrics on displays
// other than the display the context is associated with.
- final Context context = mContext.getDisplayId() == displayId
- ? mContext : mContext.getApplicationContext();
+ final Resources resources = mContext.getDisplayId() == displayId
+ ? mContext.getResources() : null;
- display = mGlobal.getCompatibleDisplay(displayId, context.getResources());
+ display = mGlobal.getCompatibleDisplay(displayId, resources);
if (display != null) {
mDisplays.put(displayId, display);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f6633201..1d759af 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14360,46 +14360,74 @@
/**
* Activity Action: Show setting page to process the addition of Wi-Fi networks to the user's
- * saved network list. The app should send a new intent with an extra that holds a maximum of
- * five {@link android.net.wifi.WifiConfiguration} that specify credentials for the networks to
- * be added to the user's database. The Intent should be sent via the {@link
- * android.app.Activity#startActivityForResult(Intent, int)} API.
+ * saved network list. The app should send a new intent with an extra that holds a maximum
+ * of five {@link android.net.wifi.WifiNetworkSuggestion} that specify credentials for the
+ * networks to be added to the user's database. The Intent should be sent via the
+ * {@link android.app.Activity#startActivityForResult(Intent, int)} API.
* <p>
* Note: The app sending the Intent to add the credentials doesn't get any ownership over the
* newly added network(s). For the Wi-Fi stack, these networks will look like the user
* manually added them from the Settings UI.
* <p>
- * Input: The app should put parcelable array list to
- * {@link android.net.wifi.WifiConfiguration} into the
- * {@link #EXTRA_WIFI_CONFIGURATION_LIST} extra.
+ * Input: The app should put parcelable array list of
+ * {@link android.net.wifi.WifiNetworkSuggestion} into the {@link #EXTRA_WIFI_NETWORK_LIST}
+ * extra.
* <p>
* Output: After {@link android.app.Activity#startActivityForResult(Intent, int)}, the
* callback {@link android.app.Activity#onActivityResult(int, int, Intent)} will have a
* result code {@link android.app.Activity#RESULT_OK} to indicate user pressed the save
* button to save the networks or {@link android.app.Activity#RESULT_CANCELED} to indicate
* that the user rejected the request. Additionally, an integer array list, stored in
- * {@link #EXTRA_WIFI_CONFIGURATION_RESULT_LIST}, will indicate the process result of
- * each network.
+ * {@link #EXTRA_WIFI_NETWORK_RESULT_LIST}, will indicate the process result of each network.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_WIFI_ADD_NETWORKS =
"android.settings.WIFI_ADD_NETWORKS";
/**
- * A bundle extra of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that indicates all the
- * {@link android.net.wifi.WifiConfiguration} that would be saved.
+ * A bundle extra of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that indicates the list
+ * of the {@link android.net.wifi.WifiNetworkSuggestion} elements. The maximum count of the
+ * {@link android.net.wifi.WifiNetworkSuggestion} elements in the list will be five.
+ * <p>
+ * For example:
+ * To provide credentials for one open and one WPA2 networks:
+ *
+ * <pre>{@code
+ * final WifiNetworkSuggestion suggestion1 =
+ * new WifiNetworkSuggestion.Builder()
+ * .setSsid("test111111")
+ * .build();
+ * final WifiNetworkSuggestion suggestion2 =
+ * new WifiNetworkSuggestion.Builder()
+ * .setSsid("test222222")
+ * .setWpa2Passphrase("test123456")
+ * .build();
+ * final List<WifiNetworkSuggestion> suggestionsList = new ArrayList<>;
+ * suggestionsList.add(suggestion1);
+ * suggestionsList.add(suggestion2);
+ * Bundle bundle = new Bundle();
+ * bundle.putParcelableArrayList(Settings.EXTRA_WIFI_NETWORK_LIST,(ArrayList<? extends
+ * Parcelable>) suggestionsList);
+ * final Intent intent = new Intent(Settings.ACTION_WIFI_ADD_NETWORKS);
+ * intent.putExtras(bundle);
+ * startActivityForResult(intent, 0);
+ * }</pre>
*/
- public static final String EXTRA_WIFI_CONFIGURATION_LIST =
- "android.provider.extra.WIFI_CONFIGURATION_LIST";
+ public static final String EXTRA_WIFI_NETWORK_LIST =
+ "android.provider.extra.WIFI_NETWORK_LIST";
/**
* A bundle extra of the result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that
- * indicates the action result of the saved {@link android.net.wifi.WifiConfiguration}. It's
- * value of AddWifiResult interface, and will be 1:1 mapping to the element in {@link
- * #EXTRA_WIFI_CONFIGURATION_LIST}.
+ * indicates the action result of the saved {@link android.net.wifi.WifiNetworkSuggestion}.
+ * Its value is a list of integers, and all the elements will be 1:1 mapping to the elements
+ * in {@link #EXTRA_WIFI_NETWORK_LIST}, if user press cancel to cancel the add networks
+ * request, then its value will be null.
+ * <p>
+ * Note: The integer value will be one of the {@link #ADD_WIFI_RESULT_SUCCESS},
+ * {@link #ADD_WIFI_RESULT_ADD_OR_UPDATE_FAILED}, or {@link #ADD_WIFI_RESULT_ALREADY_EXISTS}}.
*/
- public static final String EXTRA_WIFI_CONFIGURATION_RESULT_LIST =
- "android.provider.extra.WIFI_CONFIGURATION_RESULT_LIST";
+ public static final String EXTRA_WIFI_NETWORK_RESULT_LIST =
+ "android.provider.extra.WIFI_NETWORK_RESULT_LIST";
/** @hide */
@Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 178b3c0..904c510 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -454,7 +454,7 @@
mResources = res;
mDisplayAdjustments = mResources != null
? new DisplayAdjustments(mResources.getConfiguration())
- : daj != null ? new DisplayAdjustments(daj) : null;
+ : daj != null ? new DisplayAdjustments(daj) : new DisplayAdjustments();
mIsValid = true;
// Cache properties that cannot change as long as the display is valid.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index cc4278b..38416ee 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -159,7 +159,6 @@
private static native DisplayedContentSample nativeGetDisplayedContentSample(
IBinder displayToken, long numFrames, long timestamp);
private static native int nativeGetActiveConfig(IBinder displayToken);
- private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
private static native boolean nativeSetDesiredDisplayConfigSpecs(IBinder displayToken,
SurfaceControl.DesiredDisplayConfigSpecs desiredDisplayConfigSpecs);
private static native SurfaceControl.DesiredDisplayConfigSpecs
@@ -1482,16 +1481,6 @@
/**
- * @hide
- */
- public static boolean setActiveConfig(IBinder displayToken, int id) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
- return nativeSetActiveConfig(displayToken, id);
- }
-
- /**
* Contains information about desired display configuration.
*
* @hide
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 562ed0e..6724e9d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12602,11 +12602,10 @@
return findViewInsideOutShouldExist(root, mNextFocusForwardId);
case FOCUS_BACKWARD: {
if (mID == View.NO_ID) return null;
- final int id = mID;
return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
@Override
public boolean test(View t) {
- return t.mNextFocusForwardId == id;
+ return t.findViewById(t.mNextFocusForwardId) == View.this;
}
});
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 3dfeffb..9cbba87 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -1444,6 +1444,29 @@
return null;
}
+ /**
+ *
+ * Sets an {@link IWindowMagnificationConnection} that manipulates window magnification.
+ *
+ * @param connection The connection that manipulates window magnification.
+ * @hide
+ */
+ public void setWindowMagnificationConnection(@Nullable
+ IWindowMagnificationConnection connection) {
+ final IAccessibilityManager service;
+ synchronized (mLock) {
+ service = getServiceLocked();
+ if (service == null) {
+ return;
+ }
+ }
+ try {
+ service.setWindowMagnificationConnection(connection);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error setting window magnfication connection", re);
+ }
+ }
+
private IAccessibilityManager getServiceLocked() {
if (mService == null) {
tryConnectToServiceLocked(null);
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index fcaaa2e..7f8fdf8 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -25,6 +25,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityManagerClient;
+import android.view.accessibility.IWindowMagnificationConnection;
import android.view.IWindow;
/**
@@ -86,4 +87,5 @@
oneway void registerSystemAction(in RemoteAction action, int actionId);
oneway void unregisterSystemAction(int actionId);
+ oneway void setWindowMagnificationConnection(in IWindowMagnificationConnection connection);
}
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
new file mode 100644
index 0000000..0b45c6b
--- /dev/null
+++ b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility;
+
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.view.accessibility.IWindowMagnificationConnectionCallback;
+
+/**
+ * Interface for interaction between {@link AccessibilityManagerService}
+ * and {@link WindowMagnification} in SystemUI.
+ *
+ * @hide
+ */
+oneway interface IWindowMagnificationConnection {
+
+ /**
+ * Enables window magnification on specifed display with specified center and scale.
+ *
+ * @param displayId The logical display id.
+ * @param scale magnification scale.
+ * @param centerX the screen-relative X coordinate around which to center,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param centerY the screen-relative Y coordinate around which to center,
+ * or {@link Float#NaN} to leave unchanged.
+ */
+ void enableWindowMagnification(int displayId, float scale, float centerX, float centerY);
+
+ /**
+ * Sets the scale of the window magnifier on specifed display.
+ *
+ * @param displayId The logical display id.
+ * @param scale magnification scale.
+ */
+ void setScale(int displayId, float scale);
+
+ /**
+ * Disables window magnification on specifed display.
+ *
+ * @param displayId The logical display id.
+ */
+ void disableWindowMagnification(int displayId);
+
+ /**
+ * Moves the window magnifier on the specifed display.
+ *
+ * @param offsetX the amount in pixels to offset the window magnifier in the X direction, in
+ * current screen pixels.
+ * @param offsetY the amount in pixels to offset the window magnifier in the Y direction, in
+ * current screen pixels.
+ */
+ void moveWindowMagnifier(int displayId, float offsetX, float offsetY);
+
+ /**
+ * Sets {@link IWindowMagnificationConnectionCallback} to receive the request or the callback.
+ *
+ *
+ * @param callback the interface to be called.
+ */
+ void setConnectionCallback(in IWindowMagnificationConnectionCallback callback);
+}
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl
new file mode 100644
index 0000000..7327bb5
--- /dev/null
+++ b/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility;
+
+import android.graphics.Rect;
+
+/**
+ * interface to notify the change of the window magnifier bounds and request to change
+ * the magnification mode.
+ *
+ * @hide
+ */
+ oneway interface IWindowMagnificationConnectionCallback {
+
+ /**
+ * Called when the bounds of the window magnifier is changed.
+ *
+ * @param displayId The logical display id.
+ * @param bounds The window magnifier bounds in screen coordinates.
+ */
+ void onWindowMagnifierBoundsChanged(int display, in Rect bounds);
+ /**
+ * Changes the magnification mode on specified display. It is invoked by System UI when the
+ * switch button is toggled.
+ *
+ * @param displayId The logical display id.
+ * @param magnificationMode new magnification mode.
+ */
+ void onChangeMagnificationMode(int display, int magnificationMode);
+}
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 1aa2aec..bda12b0 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -113,7 +113,7 @@
* Returns the text that was used to generate these links.
*/
@NonNull
- public String getText() {
+ public CharSequence getText() {
return mFullText;
}
@@ -370,8 +370,8 @@
}
/**
- * @return ordered list of locale preferences that can be used to disambiguate
- * the provided text
+ * Returns an ordered list of locale preferences that can be used to disambiguate the
+ * provided text.
*/
@Nullable
public LocaleList getDefaultLocales() {
@@ -379,7 +379,8 @@
}
/**
- * @return The config representing the set of entities to look for
+ * Returns the config representing the set of entities to look for
+ *
* @see Builder#setEntityConfig(EntityConfig)
*/
@Nullable
@@ -398,8 +399,8 @@
}
/**
- * @return reference time based on which relative dates (e.g. "tomorrow") should be
- * interpreted.
+ * Returns reference time based on which relative dates (e.g. "tomorrow") should be
+ * interpreted.
*/
@Nullable
public ZonedDateTime getReferenceTime() {
@@ -473,6 +474,9 @@
}
/**
+ * Sets ordered list of locale preferences that may be used to disambiguate the
+ * provided text.
+ *
* @param defaultLocales ordered list of locale preferences that may be used to
* disambiguate the provided text. If no locale preferences exist,
* set this to null or an empty locale list.
@@ -524,9 +528,11 @@
}
/**
- * @param referenceTime reference time based on which relative dates (e.g. "tomorrow"
- * should be interpreted. This should usually be the time when the text was
- * originally composed.
+ * Sets the reference time based on which relative dates (e.g.
+ * "tomorrow") should be interpreted.
+ *
+ * @param referenceTime reference time based on which relative dates. This should
+ * usually be the time when the text was originally composed.
*
* @return this builder
*/
@@ -716,6 +722,8 @@
}
/**
+ * Adds a TextLink.
+ *
* @see #addLink(int, int, Map)
* @param urlSpan An optional URLSpan to delegate to. NOTE: Not parcelled.
*/
diff --git a/core/java/android/view/textclassifier/TextLinksParams.java b/core/java/android/view/textclassifier/TextLinksParams.java
index b7d63bf..f12b0d7 100644
--- a/core/java/android/view/textclassifier/TextLinksParams.java
+++ b/core/java/android/view/textclassifier/TextLinksParams.java
@@ -113,7 +113,7 @@
return TextLinks.STATUS_UNSUPPORTED_CHARACTER;
}
- if (!textString.startsWith(textLinks.getText())) {
+ if (!textString.startsWith(textLinks.getText().toString())) {
return TextLinks.STATUS_DIFFERENT_TEXT;
}
if (textLinks.getLinks().isEmpty()) {
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index 3fdedc8..93659a4 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -371,7 +371,9 @@
// targets during boot. Needs to read settings directly here.
String shortcutTargets = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, mUserId);
- if (TextUtils.isEmpty(shortcutTargets)) {
+ // A11y warning dialog updates settings to empty string, when user disables a11y shortcut.
+ // Only fallback to default a11y service, when setting is never updated.
+ if (shortcutTargets == null) {
shortcutTargets = mContext.getString(R.string.config_defaultAccessibilityService);
}
return !TextUtils.isEmpty(shortcutTargets);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 573f378..50a60a9 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -826,13 +826,6 @@
return static_cast<jint>(SurfaceComposerClient::getActiveConfig(token));
}
-static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj, jint id) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == NULL) return JNI_FALSE;
- status_t err = SurfaceComposerClient::setActiveConfig(token, static_cast<int>(id));
- return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
-}
-
static jintArray nativeGetDisplayColorModes(JNIEnv* env, jclass, jobject tokenObj) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return NULL;
@@ -1400,8 +1393,6 @@
(void*)nativeGetDisplayConfigs },
{"nativeGetActiveConfig", "(Landroid/os/IBinder;)I",
(void*)nativeGetActiveConfig },
- {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
- (void*)nativeSetActiveConfig },
{"nativeSetDesiredDisplayConfigSpecs",
"(Landroid/os/IBinder;Landroid/view/SurfaceControl$DesiredDisplayConfigSpecs;)Z",
(void*)nativeSetDesiredDisplayConfigSpecs },
diff --git a/core/tests/coretests/src/android/app/appsearch/SearchResultsTest.java b/core/tests/coretests/src/android/app/appsearch/SearchResultsTest.java
new file mode 100644
index 0000000..21259cc
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/SearchResultsTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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 android.app.appsearch;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import androidx.test.filters.SmallTest;
+
+import com.google.android.icing.proto.DocumentProto;
+import com.google.android.icing.proto.SearchResultProto;
+
+import org.junit.Test;
+
+@SmallTest
+public class SearchResultsTest {
+
+ @Test
+ public void testSearchResultsEqual() {
+ final String uri = "testUri";
+ final String schemaType = "testSchema";
+ SearchResultProto.ResultProto result1 = SearchResultProto.ResultProto.newBuilder()
+ .setDocument(DocumentProto.newBuilder()
+ .setUri(uri)
+ .setSchema(schemaType)
+ .build())
+ .build();
+ SearchResultProto searchResults1 = SearchResultProto.newBuilder()
+ .addResults(result1)
+ .build();
+ SearchResults res1 = new SearchResults(searchResults1);
+ SearchResultProto.ResultProto result2 = SearchResultProto.ResultProto.newBuilder()
+ .setDocument(DocumentProto.newBuilder()
+ .setUri(uri)
+ .setSchema(schemaType)
+ .build())
+ .build();
+ SearchResultProto searchResults2 = SearchResultProto.newBuilder()
+ .addResults(result2)
+ .build();
+ SearchResults res2 = new SearchResults(searchResults2);
+ assertThat(res1.toString()).isEqualTo(res2.toString());
+ }
+
+ @Test
+ public void buildSearchSpecWithoutTermMatchType() {
+ assertThrows(RuntimeException.class, () -> SearchSpec.newBuilder()
+ .setSchemaTypes("testSchemaType")
+ .build());
+ }
+}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index 1410f4f..09ea1b1 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -124,7 +124,7 @@
assertArrayEquals(new int[] {}, path(ON_START));
assertArrayEquals(new int[] {ON_RESUME}, path(ON_RESUME));
assertArrayEquals(new int[] {ON_RESUME, ON_PAUSE}, path(ON_PAUSE));
- assertArrayEquals(new int[] {ON_RESUME, ON_PAUSE, ON_STOP}, path(ON_STOP));
+ assertArrayEquals(new int[] {ON_STOP}, path(ON_STOP));
assertArrayEquals(new int[] {ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY}, path(ON_DESTROY));
}
@@ -362,7 +362,9 @@
public void testClosestStateResolutionFromOnStart() {
mClientRecord.setState(ON_START);
assertEquals(ON_RESUME, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
- new int[] {ON_CREATE, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY})));
+ new int[] {ON_CREATE, ON_RESUME, ON_PAUSE, ON_DESTROY})));
+ assertEquals(ON_STOP, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
+ new int[] {ON_STOP})));
assertEquals(ON_CREATE, mExecutorHelper.getClosestOfStates(mClientRecord, shuffledArray(
new int[] {ON_CREATE})));
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java
index e23c51e..8e24907 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityManagerTest.java
@@ -46,6 +46,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -193,4 +194,15 @@
}
});
}
+
+ @Test
+ public void testSetWindowMagnificationConnection() throws Exception {
+ AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);
+ IWindowMagnificationConnection connection = Mockito.mock(
+ IWindowMagnificationConnection.class);
+
+ manager.setWindowMagnificationConnection(connection);
+
+ verify(mMockService).setWindowMagnificationConnection(connection);
+ }
}
diff --git a/media/java/android/media/tv/tuner/Descrambler.java b/media/java/android/media/tv/tuner/Descrambler.java
index 0143582..23016e9 100644
--- a/media/java/android/media/tv/tuner/Descrambler.java
+++ b/media/java/android/media/tv/tuner/Descrambler.java
@@ -34,7 +34,7 @@
*/
public class Descrambler implements AutoCloseable {
/** @hide */
- @IntDef(prefix = "PID_TYPE_", value = {PID_TYPE_T, PID_TYPE_MMPT})
+ @IntDef(prefix = "PID_TYPE_", value = {PID_TYPE_T, PID_TYPE_MMTP})
@Retention(RetentionPolicy.SOURCE)
public @interface PidType {}
@@ -45,7 +45,7 @@
/**
* Packet ID is used to specify packets in MMTP.
*/
- public static final int PID_TYPE_MMPT = 2;
+ public static final int PID_TYPE_MMTP = 2;
private long mNativeContext;
diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java
index 8e579bf..a9a15d9 100644
--- a/media/java/android/media/tv/tuner/Lnb.java
+++ b/media/java/android/media/tv/tuner/Lnb.java
@@ -40,7 +40,8 @@
@SystemApi
public class Lnb implements AutoCloseable {
/** @hide */
- @IntDef({VOLTAGE_NONE, VOLTAGE_5V, VOLTAGE_11V, VOLTAGE_12V, VOLTAGE_13V, VOLTAGE_14V,
+ @IntDef(prefix = "VOLTAGE_",
+ value = {VOLTAGE_NONE, VOLTAGE_5V, VOLTAGE_11V, VOLTAGE_12V, VOLTAGE_13V, VOLTAGE_14V,
VOLTAGE_15V, VOLTAGE_18V, VOLTAGE_19V})
@Retention(RetentionPolicy.SOURCE)
public @interface Voltage {}
@@ -83,7 +84,8 @@
public static final int VOLTAGE_19V = Constants.LnbVoltage.VOLTAGE_19V;
/** @hide */
- @IntDef({TONE_NONE, TONE_CONTINUOUS})
+ @IntDef(prefix = "TONE_",
+ value = {TONE_NONE, TONE_CONTINUOUS})
@Retention(RetentionPolicy.SOURCE)
public @interface Tone {}
@@ -97,7 +99,8 @@
public static final int TONE_CONTINUOUS = Constants.LnbTone.CONTINUOUS;
/** @hide */
- @IntDef({POSITION_UNDEFINED, POSITION_A, POSITION_B})
+ @IntDef(prefix = "POSITION_",
+ value = {POSITION_UNDEFINED, POSITION_A, POSITION_B})
@Retention(RetentionPolicy.SOURCE)
public @interface Position {}
@@ -114,6 +117,37 @@
*/
public static final int POSITION_B = Constants.LnbPosition.POSITION_B;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "EVENT_TYPE_",
+ value = {EVENT_TYPE_DISEQC_RX_OVERFLOW, EVENT_TYPE_DISEQC_RX_TIMEOUT,
+ EVENT_TYPE_DISEQC_RX_PARITY_ERROR, EVENT_TYPE_LNB_OVERLOAD})
+ public @interface EventType {}
+
+ /**
+ * Outgoing Diseqc message overflow.
+ * @hide
+ */
+ public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW =
+ Constants.LnbEventType.DISEQC_RX_OVERFLOW;
+ /**
+ * Outgoing Diseqc message isn't delivered on time.
+ * @hide
+ */
+ public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT =
+ Constants.LnbEventType.DISEQC_RX_TIMEOUT;
+ /**
+ * Incoming Diseqc message has parity error.
+ * @hide
+ */
+ public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR =
+ Constants.LnbEventType.DISEQC_RX_PARITY_ERROR;
+ /**
+ * LNB is overload.
+ * @hide
+ */
+ public static final int EVENT_TYPE_LNB_OVERLOAD = Constants.LnbEventType.LNB_OVERLOAD;
+
int mId;
LnbCallback mCallback;
Context mContext;
diff --git a/media/java/android/media/tv/tuner/LnbCallback.java b/media/java/android/media/tv/tuner/LnbCallback.java
index 99bbf86..5155f60 100644
--- a/media/java/android/media/tv/tuner/LnbCallback.java
+++ b/media/java/android/media/tv/tuner/LnbCallback.java
@@ -17,6 +17,8 @@
package android.media.tv.tuner;
+import android.media.tv.tuner.Lnb.EventType;
+
/**
* Callback interface for receiving information from LNBs.
*
@@ -26,7 +28,7 @@
/**
* Invoked when there is a LNB event.
*/
- void onEvent(int lnbEventType);
+ void onEvent(@EventType int lnbEventType);
/**
* Invoked when there is a new DiSEqC message.
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 18969ae..3a8ae92 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -24,13 +24,13 @@
import android.annotation.SystemApi;
import android.content.Context;
import android.media.tv.tuner.TunerConstants.FilterStatus;
-import android.media.tv.tuner.TunerConstants.FilterSubtype;
import android.media.tv.tuner.TunerConstants.FrontendScanType;
import android.media.tv.tuner.TunerConstants.Result;
import android.media.tv.tuner.dvr.Dvr;
import android.media.tv.tuner.dvr.DvrCallback;
import android.media.tv.tuner.dvr.DvrSettings;
-import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
+import android.media.tv.tuner.filter.Filter.Subtype;
+import android.media.tv.tuner.filter.Filter.Type;
import android.media.tv.tuner.filter.FilterEvent;
import android.media.tv.tuner.filter.TimeFilter;
import android.media.tv.tuner.frontend.FrontendCallback;
@@ -102,7 +102,8 @@
* TODO: replace the other constructor
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
- public Tuner(@NonNull Context context, @NonNull String tvInputSessionId, int useCase) {
+ public Tuner(@NonNull Context context, @NonNull String tvInputSessionId, int useCase,
+ @Nullable OnResourceLostListener listener) {
mContext = context;
}
@@ -113,7 +114,8 @@
*
* @hide
*/
- public void shareFrontend(@NonNull Tuner tuner) { }
+ public void shareFrontendFromTuner(@NonNull Tuner tuner) {
+ }
private long mNativeContext; // used by native jMediaTuner
@@ -513,18 +515,18 @@
* @param subType the subtype of the filter.
* @param bufferSize the buffer size of the filter to be opened in bytes. The buffer holds the
* data output from the filter.
- * @param cb the callback to receive notifications from filter.
* @param executor the executor on which callback will be invoked. The default event handler
* executor is used if it's {@code null}.
+ * @param cb the callback to receive notifications from filter.
* @return the opened filter. {@code null} if the operation failed.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
- public Filter openFilter(@FilterType int mainType, @FilterSubtype int subType,
- @BytesLong long bufferSize, @Nullable FilterCallback cb,
- @CallbackExecutor @Nullable Executor executor) {
+ public Filter openFilter(@Type int mainType, @Subtype int subType,
+ @BytesLong long bufferSize, @CallbackExecutor @Nullable Executor executor,
+ @Nullable FilterCallback cb) {
TunerUtils.checkTunerPermission(mContext);
Filter filter = nativeOpenFilter(
mainType, TunerUtils.getFilterSubtype(mainType, subType), bufferSize);
@@ -540,16 +542,34 @@
/**
* Opens an LNB (low-noise block downconverter) object.
*
- * @param cb the callback to receive notifications from LNB.
* @param executor the executor on which callback will be invoked. The default event handler
* executor is used if it's {@code null}.
+ * @param cb the callback to receive notifications from LNB.
* @return the opened LNB object. {@code null} if the operation failed.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
- public Lnb openLnb(LnbCallback cb, @CallbackExecutor @Nullable Executor executor) {
+ public Lnb openLnb(@CallbackExecutor @Nullable Executor executor, LnbCallback cb) {
+ return openLnbByName(null, executor, cb);
+ }
+
+ /**
+ * Opens an LNB (low-noise block downconverter) object.
+ *
+ * @param name the LNB name.
+ * @param executor the executor on which callback will be invoked. The default event handler
+ * executor is used if it's {@code null}.
+ * @param cb the callback to receive notifications from LNB.
+ * @return the opened LNB object. {@code null} if the operation failed.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
+ @Nullable
+ public Lnb openLnbByName(@Nullable String name, @CallbackExecutor @Nullable Executor executor,
+ LnbCallback cb) {
TunerUtils.checkTunerPermission(mContext);
// TODO: use resource manager to get LNB ID.
return new Lnb(0);
@@ -608,17 +628,17 @@
* @param type the DVR type to be opened.
* @param bufferSize the buffer size of the output in bytes. It's used to hold output data of
* the attached filters.
- * @param cb the callback to receive notifications from DVR.
* @param executor the executor on which callback will be invoked. The default event handler
* executor is used if it's {@code null}.
+ * @param cb the callback to receive notifications from DVR.
* @return the opened DVR object. {@code null} if the operation failed.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
- public Dvr openDvr(@DvrSettings.Type int type, @BytesLong long bufferSize, DvrCallback cb,
- @CallbackExecutor @Nullable Executor executor) {
+ public Dvr openDvr(@DvrSettings.Type int type, @BytesLong long bufferSize,
+ @CallbackExecutor @Nullable Executor executor, DvrCallback cb) {
TunerUtils.checkTunerPermission(mContext);
Dvr dvr = nativeOpenDvr(type, bufferSize);
return dvr;
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index fa8f550..fe4c954 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -36,69 +36,42 @@
*/
@SystemApi
public final class TunerConstants {
- /** @hide */
+ /**
+ * Invalid TS packet ID.
+ * @hide
+ */
public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
- /** @hide */
+ /**
+ * Invalid stream ID.
+ * @hide
+ */
public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
/** @hide */
- @IntDef({FRONTEND_EVENT_TYPE_LOCKED, FRONTEND_EVENT_TYPE_NO_SIGNAL,
- FRONTEND_EVENT_TYPE_LOST_LOCK})
+ @IntDef(prefix = "FRONTEND_EVENT_TYPE_",
+ value = {FRONTEND_EVENT_TYPE_LOCKED, FRONTEND_EVENT_TYPE_NO_SIGNAL,
+ FRONTEND_EVENT_TYPE_LOST_LOCK})
@Retention(RetentionPolicy.SOURCE)
public @interface FrontendEventType {}
- /** @hide */
+ /**
+ * Frontend locked.
+ * @hide
+ */
public static final int FRONTEND_EVENT_TYPE_LOCKED = Constants.FrontendEventType.LOCKED;
- /** @hide */
+ /**
+ * No signal detected.
+ * @hide
+ */
public static final int FRONTEND_EVENT_TYPE_NO_SIGNAL = Constants.FrontendEventType.NO_SIGNAL;
- /** @hide */
+ /**
+ * Frontend lock lost.
+ * @hide
+ */
public static final int FRONTEND_EVENT_TYPE_LOST_LOCK = Constants.FrontendEventType.LOST_LOCK;
/** @hide */
- @IntDef({FILTER_SUBTYPE_UNDEFINED, FILTER_SUBTYPE_SECTION, FILTER_SUBTYPE_PES,
- FILTER_SUBTYPE_AUDIO, FILTER_SUBTYPE_VIDEO, FILTER_SUBTYPE_DOWNLOAD,
- FILTER_SUBTYPE_RECORD, FILTER_SUBTYPE_TS, FILTER_SUBTYPE_PCR, FILTER_SUBTYPE_TEMI,
- FILTER_SUBTYPE_MMPT, FILTER_SUBTYPE_NTP, FILTER_SUBTYPE_IP_PAYLOAD, FILTER_SUBTYPE_IP,
- FILTER_SUBTYPE_PAYLOAD_THROUGH, FILTER_SUBTYPE_TLV, FILTER_SUBTYPE_PTP, })
- @Retention(RetentionPolicy.SOURCE)
- public @interface FilterSubtype {}
- /** @hide */
- public static final int FILTER_SUBTYPE_UNDEFINED = 0;
- /** @hide */
- public static final int FILTER_SUBTYPE_SECTION = 1;
- /** @hide */
- public static final int FILTER_SUBTYPE_PES = 2;
- /** @hide */
- public static final int FILTER_SUBTYPE_AUDIO = 3;
- /** @hide */
- public static final int FILTER_SUBTYPE_VIDEO = 4;
- /** @hide */
- public static final int FILTER_SUBTYPE_DOWNLOAD = 5;
- /** @hide */
- public static final int FILTER_SUBTYPE_RECORD = 6;
- /** @hide */
- public static final int FILTER_SUBTYPE_TS = 7;
- /** @hide */
- public static final int FILTER_SUBTYPE_PCR = 8;
- /** @hide */
- public static final int FILTER_SUBTYPE_TEMI = 9;
- /** @hide */
- public static final int FILTER_SUBTYPE_MMPT = 10;
- /** @hide */
- public static final int FILTER_SUBTYPE_NTP = 11;
- /** @hide */
- public static final int FILTER_SUBTYPE_IP_PAYLOAD = 12;
- /** @hide */
- public static final int FILTER_SUBTYPE_IP = 13;
- /** @hide */
- public static final int FILTER_SUBTYPE_PAYLOAD_THROUGH = 14;
- /** @hide */
- public static final int FILTER_SUBTYPE_TLV = 15;
- /** @hide */
- public static final int FILTER_SUBTYPE_PTP = 16;
-
- /** @hide */
@IntDef(flag = true, prefix = "FILTER_STATUS_", value = {FILTER_STATUS_DATA_READY,
FILTER_STATUS_LOW_WATER, FILTER_STATUS_HIGH_WATER, FILTER_STATUS_OVERFLOW})
@Retention(RetentionPolicy.SOURCE)
@@ -502,23 +475,6 @@
/** @hide */
- @IntDef({FILTER_SETTINGS_TS, FILTER_SETTINGS_MMTP, FILTER_SETTINGS_IP, FILTER_SETTINGS_TLV,
- FILTER_SETTINGS_ALP})
- @Retention(RetentionPolicy.SOURCE)
- public @interface FilterSettingsType {}
- /** @hide */
- public static final int FILTER_SETTINGS_TS = Constants.DemuxFilterMainType.TS;
- /** @hide */
- public static final int FILTER_SETTINGS_MMTP = Constants.DemuxFilterMainType.MMTP;
- /** @hide */
- public static final int FILTER_SETTINGS_IP = Constants.DemuxFilterMainType.IP;
- /** @hide */
- public static final int FILTER_SETTINGS_TLV = Constants.DemuxFilterMainType.TLV;
- /** @hide */
- public static final int FILTER_SETTINGS_ALP = Constants.DemuxFilterMainType.ALP;
-
-
- /** @hide */
@IntDef({RESULT_SUCCESS, RESULT_UNAVAILABLE, RESULT_NOT_INITIALIZED, RESULT_INVALID_STATE,
RESULT_INVALID_ARGUMENT, RESULT_OUT_OF_MEMORY, RESULT_UNKNOWN_ERROR})
@Retention(RetentionPolicy.SOURCE)
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index 8780b72..30aaa02 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -19,9 +19,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.TunerConstants.FilterSubtype;
-import android.media.tv.tuner.filter.FilterConfiguration;
-import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
+import android.media.tv.tuner.filter.Filter;
/**
* Utility class for tuner framework.
@@ -50,91 +48,91 @@
* @param mainType filter main type.
* @param subtype filter subtype.
*/
- public static int getFilterSubtype(@FilterType int mainType, @FilterSubtype int subtype) {
- if (mainType == FilterConfiguration.FILTER_TYPE_TS) {
+ public static int getFilterSubtype(@Filter.Type int mainType, @Filter.Subtype int subtype) {
+ if (mainType == Filter.TYPE_TS) {
switch (subtype) {
- case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ case Filter.SUBTYPE_UNDEFINED:
return Constants.DemuxTsFilterType.UNDEFINED;
- case TunerConstants.FILTER_SUBTYPE_SECTION:
+ case Filter.SUBTYPE_SECTION:
return Constants.DemuxTsFilterType.SECTION;
- case TunerConstants.FILTER_SUBTYPE_PES:
+ case Filter.SUBTYPE_PES:
return Constants.DemuxTsFilterType.PES;
- case TunerConstants.FILTER_SUBTYPE_TS:
+ case Filter.SUBTYPE_TS:
return Constants.DemuxTsFilterType.TS;
- case TunerConstants.FILTER_SUBTYPE_AUDIO:
+ case Filter.SUBTYPE_AUDIO:
return Constants.DemuxTsFilterType.AUDIO;
- case TunerConstants.FILTER_SUBTYPE_VIDEO:
+ case Filter.SUBTYPE_VIDEO:
return Constants.DemuxTsFilterType.VIDEO;
- case TunerConstants.FILTER_SUBTYPE_PCR:
+ case Filter.SUBTYPE_PCR:
return Constants.DemuxTsFilterType.PCR;
- case TunerConstants.FILTER_SUBTYPE_RECORD:
+ case Filter.SUBTYPE_RECORD:
return Constants.DemuxTsFilterType.RECORD;
- case TunerConstants.FILTER_SUBTYPE_TEMI:
+ case Filter.SUBTYPE_TEMI:
return Constants.DemuxTsFilterType.TEMI;
default:
break;
}
- } else if (mainType == FilterConfiguration.FILTER_TYPE_MMTP) {
+ } else if (mainType == Filter.TYPE_MMTP) {
switch (subtype) {
- case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ case Filter.SUBTYPE_UNDEFINED:
return Constants.DemuxMmtpFilterType.UNDEFINED;
- case TunerConstants.FILTER_SUBTYPE_SECTION:
+ case Filter.SUBTYPE_SECTION:
return Constants.DemuxMmtpFilterType.SECTION;
- case TunerConstants.FILTER_SUBTYPE_PES:
+ case Filter.SUBTYPE_PES:
return Constants.DemuxMmtpFilterType.PES;
- case TunerConstants.FILTER_SUBTYPE_MMPT:
+ case Filter.SUBTYPE_MMTP:
return Constants.DemuxMmtpFilterType.MMTP;
- case TunerConstants.FILTER_SUBTYPE_AUDIO:
+ case Filter.SUBTYPE_AUDIO:
return Constants.DemuxMmtpFilterType.AUDIO;
- case TunerConstants.FILTER_SUBTYPE_VIDEO:
+ case Filter.SUBTYPE_VIDEO:
return Constants.DemuxMmtpFilterType.VIDEO;
- case TunerConstants.FILTER_SUBTYPE_RECORD:
+ case Filter.SUBTYPE_RECORD:
return Constants.DemuxMmtpFilterType.RECORD;
- case TunerConstants.FILTER_SUBTYPE_DOWNLOAD:
+ case Filter.SUBTYPE_DOWNLOAD:
return Constants.DemuxMmtpFilterType.DOWNLOAD;
default:
break;
}
- } else if (mainType == FilterConfiguration.FILTER_TYPE_IP) {
+ } else if (mainType == Filter.TYPE_IP) {
switch (subtype) {
- case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ case Filter.SUBTYPE_UNDEFINED:
return Constants.DemuxIpFilterType.UNDEFINED;
- case TunerConstants.FILTER_SUBTYPE_SECTION:
+ case Filter.SUBTYPE_SECTION:
return Constants.DemuxIpFilterType.SECTION;
- case TunerConstants.FILTER_SUBTYPE_NTP:
+ case Filter.SUBTYPE_NTP:
return Constants.DemuxIpFilterType.NTP;
- case TunerConstants.FILTER_SUBTYPE_IP_PAYLOAD:
+ case Filter.SUBTYPE_IP_PAYLOAD:
return Constants.DemuxIpFilterType.IP_PAYLOAD;
- case TunerConstants.FILTER_SUBTYPE_IP:
+ case Filter.SUBTYPE_IP:
return Constants.DemuxIpFilterType.IP;
- case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ case Filter.SUBTYPE_PAYLOAD_THROUGH:
return Constants.DemuxIpFilterType.PAYLOAD_THROUGH;
default:
break;
}
- } else if (mainType == FilterConfiguration.FILTER_TYPE_TLV) {
+ } else if (mainType == Filter.TYPE_TLV) {
switch (subtype) {
- case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ case Filter.SUBTYPE_UNDEFINED:
return Constants.DemuxTlvFilterType.UNDEFINED;
- case TunerConstants.FILTER_SUBTYPE_SECTION:
+ case Filter.SUBTYPE_SECTION:
return Constants.DemuxTlvFilterType.SECTION;
- case TunerConstants.FILTER_SUBTYPE_TLV:
+ case Filter.SUBTYPE_TLV:
return Constants.DemuxTlvFilterType.TLV;
- case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ case Filter.SUBTYPE_PAYLOAD_THROUGH:
return Constants.DemuxTlvFilterType.PAYLOAD_THROUGH;
default:
break;
}
- } else if (mainType == FilterConfiguration.FILTER_TYPE_ALP) {
+ } else if (mainType == Filter.TYPE_ALP) {
switch (subtype) {
- case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ case Filter.SUBTYPE_UNDEFINED:
return Constants.DemuxAlpFilterType.UNDEFINED;
- case TunerConstants.FILTER_SUBTYPE_SECTION:
+ case Filter.SUBTYPE_SECTION:
return Constants.DemuxAlpFilterType.SECTION;
- case TunerConstants.FILTER_SUBTYPE_PTP:
+ case Filter.SUBTYPE_PTP:
return Constants.DemuxAlpFilterType.PTP;
- case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ case Filter.SUBTYPE_PAYLOAD_THROUGH:
return Constants.DemuxAlpFilterType.PAYLOAD_THROUGH;
default:
break;
diff --git a/media/java/android/media/tv/tuner/dvr/Dvr.java b/media/java/android/media/tv/tuner/dvr/Dvr.java
index 95508d3..a17773c 100644
--- a/media/java/android/media/tv/tuner/dvr/Dvr.java
+++ b/media/java/android/media/tv/tuner/dvr/Dvr.java
@@ -17,11 +17,16 @@
package android.media.tv.tuner.dvr;
import android.annotation.BytesLong;
+import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.Tuner.Filter;
import android.media.tv.tuner.TunerConstants.Result;
import android.os.ParcelFileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Digital Video Record (DVR) interface provides record control on Demux's output buffer and
* playback control on Demux's input buffer.
@@ -29,6 +34,37 @@
* @hide
*/
public class Dvr {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "PLAYBACK_STATUS_",
+ value = {PLAYBACK_STATUS_EMPTY, PLAYBACK_STATUS_ALMOST_EMPTY,
+ PLAYBACK_STATUS_ALMOST_FULL, PLAYBACK_STATUS_FULL})
+ @interface PlaybackStatus {}
+
+ /**
+ * The space of the playback is empty.
+ */
+ public static final int PLAYBACK_STATUS_EMPTY = Constants.PlaybackStatus.SPACE_EMPTY;
+ /**
+ * The space of the playback is almost empty.
+ *
+ * <p> the threshold is set in {@link DvrSettings}.
+ */
+ public static final int PLAYBACK_STATUS_ALMOST_EMPTY =
+ Constants.PlaybackStatus.SPACE_ALMOST_EMPTY;
+ /**
+ * The space of the playback is almost full.
+ *
+ * <p> the threshold is set in {@link DvrSettings}.
+ */
+ public static final int PLAYBACK_STATUS_ALMOST_FULL =
+ Constants.PlaybackStatus.SPACE_ALMOST_FULL;
+ /**
+ * The space of the playback is full.
+ */
+ public static final int PLAYBACK_STATUS_FULL = Constants.PlaybackStatus.SPACE_FULL;
+
+
private long mNativeContext;
private DvrCallback mCallback;
diff --git a/media/java/android/media/tv/tuner/dvr/DvrCallback.java b/media/java/android/media/tv/tuner/dvr/DvrCallback.java
index 3d140f0..ee0cfa7d 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrCallback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrCallback.java
@@ -16,6 +16,9 @@
package android.media.tv.tuner.dvr;
+import android.media.tv.tuner.TunerConstants.FilterStatus;
+import android.media.tv.tuner.dvr.Dvr.PlaybackStatus;
+
/**
* Callback interface for receiving information from DVR interfaces.
*
@@ -25,9 +28,9 @@
/**
* Invoked when record status changed.
*/
- void onRecordStatusChanged(int status);
+ void onRecordStatusChanged(@FilterStatus int status);
/**
* Invoked when playback status changed.
*/
- void onPlaybackStatusChanged(int status);
+ void onPlaybackStatusChanged(@PlaybackStatus int status);
}
diff --git a/media/java/android/media/tv/tuner/dvr/DvrSettings.java b/media/java/android/media/tv/tuner/dvr/DvrSettings.java
index 46efd7a..49e875a 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrSettings.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrSettings.java
@@ -19,8 +19,11 @@
import android.annotation.BytesLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.content.Context;
import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.TunerConstants.FilterStatus;
+import android.media.tv.tuner.TunerUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -94,9 +97,13 @@
/**
* Creates a builder for {@link DvrSettings}.
+ *
+ * @param context the context of the caller.
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
- public static Builder newBuilder() {
+ public static Builder builder(Context context) {
+ TunerUtils.checkTunerPermission(context);
return new Builder();
}
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index 940b5ae..93eaaa4 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -19,9 +19,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.content.Context;
-import android.media.tv.tuner.TunerConstants;
import android.media.tv.tuner.TunerUtils;
-import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
/**
* Filter Settings for a Video and Audio.
@@ -35,8 +33,8 @@
super(TunerUtils.getFilterSubtype(
mainType,
isAudio
- ? TunerConstants.FILTER_SUBTYPE_AUDIO
- : TunerConstants.FILTER_SUBTYPE_VIDEO));
+ ? Filter.SUBTYPE_AUDIO
+ : Filter.SUBTYPE_VIDEO));
mIsPassthrough = isPassthrough;
}
@@ -57,7 +55,7 @@
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
public static Builder builder(
- @NonNull Context context, @FilterType int mainType, boolean isAudio) {
+ @NonNull Context context, @Filter.Type int mainType, boolean isAudio) {
TunerUtils.checkTunerPermission(context);
return new Builder(mainType, isAudio);
}
diff --git a/media/java/android/media/tv/tuner/filter/DownloadSettings.java b/media/java/android/media/tv/tuner/filter/DownloadSettings.java
index e3e1df0..fa7744a 100644
--- a/media/java/android/media/tv/tuner/filter/DownloadSettings.java
+++ b/media/java/android/media/tv/tuner/filter/DownloadSettings.java
@@ -19,9 +19,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.content.Context;
-import android.media.tv.tuner.TunerConstants;
import android.media.tv.tuner.TunerUtils;
-import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
/**
* Filter Settings for a Download.
@@ -31,7 +29,7 @@
private final int mDownloadId;
private DownloadSettings(int mainType, int downloadId) {
- super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_DOWNLOAD));
+ super(TunerUtils.getFilterSubtype(mainType, Filter.SUBTYPE_DOWNLOAD));
mDownloadId = downloadId;
}
@@ -50,7 +48,7 @@
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
- public static Builder builder(@NonNull Context context, @FilterType int mainType) {
+ public static Builder builder(@NonNull Context context, @Filter.Type int mainType) {
TunerUtils.checkTunerPermission(context);
return new Builder(mainType);
}
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 804c0c5..3f6154b 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -17,9 +17,15 @@
package android.media.tv.tuner.filter;
import android.annotation.BytesLong;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.Tuner.FilterCallback;
+import android.media.tv.tuner.TunerConstants.Result;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* Tuner data filter.
@@ -29,6 +35,128 @@
* @hide
*/
public class Filter implements AutoCloseable {
+ /** @hide */
+ @IntDef(prefix = "TYPE_",
+ value = {TYPE_TS, TYPE_MMTP, TYPE_IP, TYPE_TLV, TYPE_ALP})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
+ /**
+ * TS filter type.
+ */
+ public static final int TYPE_TS = Constants.DemuxFilterMainType.TS;
+ /**
+ * MMTP filter type.
+ */
+ public static final int TYPE_MMTP = Constants.DemuxFilterMainType.MMTP;
+ /**
+ * IP filter type.
+ */
+ public static final int TYPE_IP = Constants.DemuxFilterMainType.IP;
+ /**
+ * TLV filter type.
+ */
+ public static final int TYPE_TLV = Constants.DemuxFilterMainType.TLV;
+ /**
+ * ALP filter type.
+ */
+ public static final int TYPE_ALP = Constants.DemuxFilterMainType.ALP;
+
+ /** @hide */
+ @IntDef(prefix = "SUBTYPE_",
+ value = {SUBTYPE_UNDEFINED, SUBTYPE_SECTION, SUBTYPE_PES, SUBTYPE_AUDIO, SUBTYPE_VIDEO,
+ SUBTYPE_DOWNLOAD, SUBTYPE_RECORD, SUBTYPE_TS, SUBTYPE_PCR, SUBTYPE_TEMI,
+ SUBTYPE_MMTP, SUBTYPE_NTP, SUBTYPE_IP_PAYLOAD, SUBTYPE_IP,
+ SUBTYPE_PAYLOAD_THROUGH, SUBTYPE_TLV, SUBTYPE_PTP, })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Subtype {}
+ /**
+ * Filter subtype undefined.
+ * @hide
+ */
+ public static final int SUBTYPE_UNDEFINED = 0;
+ /**
+ * Section filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_SECTION = 1;
+ /**
+ * PES filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_PES = 2;
+ /**
+ * Audio filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_AUDIO = 3;
+ /**
+ * Video filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_VIDEO = 4;
+ /**
+ * Download filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_DOWNLOAD = 5;
+ /**
+ * Record filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_RECORD = 6;
+ /**
+ * TS filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_TS = 7;
+ /**
+ * PCR filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_PCR = 8;
+ /**
+ * TEMI filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_TEMI = 9;
+ /**
+ * MMTP filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_MMTP = 10;
+ /**
+ * NTP filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_NTP = 11;
+ /**
+ * Payload filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_IP_PAYLOAD = 12;
+ /**
+ * IP filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_IP = 13;
+ /**
+ * Payload through filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_PAYLOAD_THROUGH = 14;
+ /**
+ * TLV filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_TLV = 15;
+ /**
+ * PTP filter subtype.
+ * @hide
+ */
+ public static final int SUBTYPE_PTP = 16;
+
+
private long mNativeContext;
private FilterCallback mCallback;
private final int mId;
@@ -56,6 +184,7 @@
* @param config the configuration of the filter.
* @return result status of the operation.
*/
+ @Result
public int configure(@NonNull FilterConfiguration config) {
int subType = -1;
Settings s = config.getSettings();
@@ -68,6 +197,7 @@
/**
* Gets the filter Id.
*/
+ @Result
public int getId() {
return nativeGetId();
}
@@ -84,6 +214,7 @@
* use demux as data source if the filter instance is NULL.
* @return result status of the operation.
*/
+ @Result
public int setDataSource(@Nullable Filter source) {
return nativeSetDataSource(source);
}
@@ -93,6 +224,7 @@
*
* @return result status of the operation.
*/
+ @Result
public int start() {
return nativeStartFilter();
}
@@ -103,6 +235,7 @@
*
* @return result status of the operation.
*/
+ @Result
public int stop() {
return nativeStopFilter();
}
@@ -112,6 +245,7 @@
*
* @return result status of the operation.
*/
+ @Result
public int flush() {
return nativeFlushFilter();
}
@@ -124,6 +258,7 @@
* @param size the maximum number of bytes to read.
* @return the number of bytes read.
*/
+ @Result
public int read(@NonNull byte[] buffer, @BytesLong long offset, @BytesLong long size) {
size = Math.min(size, buffer.length - offset);
return nativeRead(buffer, offset, size);
diff --git a/media/java/android/media/tv/tuner/filter/FilterConfiguration.java b/media/java/android/media/tv/tuner/filter/FilterConfiguration.java
index 68c722f..c901e2b 100644
--- a/media/java/android/media/tv/tuner/filter/FilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/FilterConfiguration.java
@@ -32,7 +32,10 @@
@SystemApi
public abstract class FilterConfiguration {
- /** @hide */
+ /**
+ * TODO: moved to Filter. Remove it here.
+ * @hide
+ */
@IntDef(prefix = "FILTER_TYPE_", value =
{FILTER_TYPE_TS, FILTER_TYPE_MMTP, FILTER_TYPE_IP, FILTER_TYPE_TLV, FILTER_TYPE_ALP})
@Retention(RetentionPolicy.SOURCE)
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index 37f94ae..0b5c56b 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -16,6 +16,7 @@
package android.media.tv.tuner.filter;
+import android.annotation.BytesLong;
import android.annotation.Nullable;
import android.media.tv.tuner.Tuner.Filter;
@@ -28,23 +29,27 @@
private final int mStreamId;
private final boolean mIsPtsPresent;
private final long mPts;
- private final int mDataLength;
+ private final long mDataLength;
+ private final long mOffset;
private final Object mLinearBuffer;
private final boolean mIsSecureMemory;
+ private final long mDataId;
private final int mMpuSequenceNumber;
private final boolean mIsPrivateData;
private final AudioDescriptor mExtraMetaData;
// This constructor is used by JNI code only
- private MediaEvent(int streamId, boolean isPtsPresent, long pts, int dataLength, Object buffer,
- boolean isSecureMemory, int mpuSequenceNumber, boolean isPrivateData,
- AudioDescriptor extraMetaData) {
+ private MediaEvent(int streamId, boolean isPtsPresent, long pts, long dataLength, long offset,
+ Object buffer, boolean isSecureMemory, long dataId, int mpuSequenceNumber,
+ boolean isPrivateData, AudioDescriptor extraMetaData) {
mStreamId = streamId;
mIsPtsPresent = isPtsPresent;
mPts = pts;
mDataLength = dataLength;
+ mOffset = offset;
mLinearBuffer = buffer;
mIsSecureMemory = isSecureMemory;
+ mDataId = dataId;
mMpuSequenceNumber = mpuSequenceNumber;
mIsPrivateData = isPrivateData;
mExtraMetaData = extraMetaData;
@@ -76,11 +81,20 @@
/**
* Gets data size in bytes of audio or video frame.
*/
- public int getDataLength() {
+ @BytesLong
+ public long getDataLength() {
return mDataLength;
}
/**
+ * The offset in the memory block which is shared among multiple Media Events.
+ */
+ @BytesLong
+ public long getOffset() {
+ return mOffset;
+ }
+
+ /**
* Gets a linear buffer associated to the memory where audio or video data stays.
* TODO: use LinearBuffer when it's ready.
*
@@ -101,6 +115,15 @@
}
/**
+ * Gets the ID which is used by HAL to provide additional information for AV data.
+ *
+ * <p>For secure audio, it's the audio handle used by Audio Track.
+ */
+ public long getAvDataId() {
+ return mDataId;
+ }
+
+ /**
* Gets MPU sequence number of filtered data.
*/
public int getMpuSequenceNumber() {
diff --git a/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java
index 83246e5..248f23a 100644
--- a/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java
@@ -39,7 +39,7 @@
}
/**
- * Gets MMPT PID.
+ * Gets MMTP PID.
*
* <p>Packet ID is used to specify packets in MMTP.
*/
@@ -69,7 +69,7 @@
}
/**
- * Sets MMPT PID.
+ * Sets MMTP PID.
*/
@NonNull
public Builder setMmtpPid(int mmtpPid) {
diff --git a/media/java/android/media/tv/tuner/filter/PesSettings.java b/media/java/android/media/tv/tuner/filter/PesSettings.java
index bfa1f8c..0f83597 100644
--- a/media/java/android/media/tv/tuner/filter/PesSettings.java
+++ b/media/java/android/media/tv/tuner/filter/PesSettings.java
@@ -20,9 +20,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
-import android.media.tv.tuner.TunerConstants;
import android.media.tv.tuner.TunerUtils;
-import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
/**
* Filter Settings for a PES Data.
@@ -34,8 +32,8 @@
private final int mStreamId;
private final boolean mIsRaw;
- private PesSettings(@FilterType int mainType, int streamId, boolean isRaw) {
- super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_PES));
+ private PesSettings(@Filter.Type int mainType, int streamId, boolean isRaw) {
+ super(TunerUtils.getFilterSubtype(mainType, Filter.SUBTYPE_PES));
mStreamId = streamId;
mIsRaw = isRaw;
}
@@ -65,7 +63,7 @@
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
- public static Builder builder(@NonNull Context context, @FilterType int mainType) {
+ public static Builder builder(@NonNull Context context, @Filter.Type int mainType) {
TunerUtils.checkTunerPermission(context);
return new Builder(mainType);
}
diff --git a/media/java/android/media/tv/tuner/filter/RecordSettings.java b/media/java/android/media/tv/tuner/filter/RecordSettings.java
index 4833709..4e9d67f 100644
--- a/media/java/android/media/tv/tuner/filter/RecordSettings.java
+++ b/media/java/android/media/tv/tuner/filter/RecordSettings.java
@@ -24,7 +24,6 @@
import android.media.tv.tuner.TunerConstants;
import android.media.tv.tuner.TunerConstants.ScIndexType;
import android.media.tv.tuner.TunerUtils;
-import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -151,7 +150,7 @@
private final int mScIndexMask;
private RecordSettings(int mainType, int tsIndexType, int scIndexType, int scIndexMask) {
- super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_RECORD));
+ super(TunerUtils.getFilterSubtype(mainType, Filter.SUBTYPE_RECORD));
mTsIndexMask = tsIndexType;
mScIndexType = scIndexType;
mScIndexMask = scIndexMask;
@@ -187,7 +186,7 @@
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
- public static Builder builder(@NonNull Context context, @FilterType int mainType) {
+ public static Builder builder(@NonNull Context context, @Filter.Type int mainType) {
TunerUtils.checkTunerPermission(context);
return new Builder(mainType);
}
diff --git a/media/java/android/media/tv/tuner/filter/SectionSettings.java b/media/java/android/media/tv/tuner/filter/SectionSettings.java
index 36e3d7c..b8d0fad 100644
--- a/media/java/android/media/tv/tuner/filter/SectionSettings.java
+++ b/media/java/android/media/tv/tuner/filter/SectionSettings.java
@@ -16,7 +16,6 @@
package android.media.tv.tuner.filter;
-import android.media.tv.tuner.TunerConstants;
import android.media.tv.tuner.TunerUtils;
/**
@@ -26,6 +25,6 @@
public class SectionSettings extends Settings {
SectionSettings(int mainType) {
- super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_SECTION));
+ super(TunerUtils.getFilterSubtype(mainType, Filter.SUBTYPE_SECTION));
}
}
diff --git a/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java b/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java
index 0fa982e..a2d42d8 100644
--- a/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java
+++ b/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java
@@ -20,7 +20,6 @@
import android.annotation.RequiresPermission;
import android.content.Context;
import android.media.tv.tuner.TunerUtils;
-import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
/**
* Bits Settings for Section Filters.
@@ -73,7 +72,7 @@
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
- public static Builder builder(@NonNull Context context, @FilterType int mainType) {
+ public static Builder builder(@NonNull Context context, @Filter.Type int mainType) {
TunerUtils.checkTunerPermission(context);
return new Builder(mainType);
}
diff --git a/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java b/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
index 6542b89..0c9cd2b 100644
--- a/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
+++ b/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
@@ -20,7 +20,6 @@
import android.annotation.RequiresPermission;
import android.content.Context;
import android.media.tv.tuner.TunerUtils;
-import android.media.tv.tuner.filter.FilterConfiguration.FilterType;
/**
* Table information for Section Filter.
@@ -57,7 +56,7 @@
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@NonNull
- public static Builder builder(@NonNull Context context, @FilterType int mainType) {
+ public static Builder builder(@NonNull Context context, @Filter.Type int mainType) {
TunerUtils.checkTunerPermission(context);
return new Builder(mainType);
}
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index 5b3bffc4..44dbcc0 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -112,31 +112,31 @@
public @interface Rolloff {}
/**
- * Roll Off undefined.
+ * Rolloff range undefined.
*/
public static final int ROLLOFF_UNDEFINED = Constants.FrontendDvbsRolloff.UNDEFINED;
/**
- * Roll Off 0_35.
+ * Rolloff range 0,35.
*/
public static final int ROLLOFF_0_35 = Constants.FrontendDvbsRolloff.ROLLOFF_0_35;
/**
- * Roll Off 0_25.
+ * Rolloff range 0,25.
*/
public static final int ROLLOFF_0_25 = Constants.FrontendDvbsRolloff.ROLLOFF_0_25;
/**
- * Roll Off 0_2.
+ * Rolloff range 0,20.
*/
public static final int ROLLOFF_0_20 = Constants.FrontendDvbsRolloff.ROLLOFF_0_20;
/**
- * Roll Off 0_15.
+ * Rolloff range 0,15.
*/
public static final int ROLLOFF_0_15 = Constants.FrontendDvbsRolloff.ROLLOFF_0_15;
/**
- * Roll Off 0_1.
+ * Rolloff range 0,10.
*/
public static final int ROLLOFF_0_10 = Constants.FrontendDvbsRolloff.ROLLOFF_0_10;
/**
- * Roll Off 0_5.
+ * Rolloff range 0,5.
*/
public static final int ROLLOFF_0_5 = Constants.FrontendDvbsRolloff.ROLLOFF_0_5;
@@ -188,6 +188,25 @@
*/
public static final int STANDARD_S2X = Constants.FrontendDvbsStandard.S2X;
+ /** @hide */
+ @IntDef(prefix = "VCM_MODE_",
+ value = {VCM_MODE_UNDEFINED, VCM_MODE_AUTO, VCM_MODE_MANUAL})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VcmMode {}
+
+ /**
+ * VCM mode undefined.
+ */
+ public static final int VCM_MODE_UNDEFINED = Constants.FrontendDvbsVcmMode.UNDEFINED;
+ /**
+ * Auto VCM mode.
+ */
+ public static final int VCM_MODE_AUTO = Constants.FrontendDvbsVcmMode.AUTO;
+ /**
+ * Manual VCM mode.
+ */
+ public static final int VCM_MODE_MANUAL = Constants.FrontendDvbsVcmMode.MANUAL;
+
private final int mModulation;
private final DvbsCodeRate mCoderate;
@@ -196,9 +215,10 @@
private final int mPilot;
private final int mInputStreamId;
private final int mStandard;
+ private final int mVcmMode;
private DvbsFrontendSettings(int frequency, int modulation, DvbsCodeRate coderate,
- int symbolRate, int rolloff, int pilot, int inputStreamId, int standard) {
+ int symbolRate, int rolloff, int pilot, int inputStreamId, int standard, int vcm) {
super(frequency);
mModulation = modulation;
mCoderate = coderate;
@@ -207,6 +227,7 @@
mPilot = pilot;
mInputStreamId = inputStreamId;
mStandard = standard;
+ mVcmMode = vcm;
}
/**
@@ -256,6 +277,13 @@
public int getStandard() {
return mStandard;
}
+ /**
+ * Gets VCM mode.
+ */
+ @VcmMode
+ public int getVcmMode() {
+ return mVcmMode;
+ }
/**
* Creates a builder for {@link DvbsFrontendSettings}.
@@ -280,6 +308,7 @@
private int mPilot;
private int mInputStreamId;
private int mStandard;
+ private int mVcmMode;
private Builder() {
}
@@ -340,6 +369,14 @@
mStandard = standard;
return this;
}
+ /**
+ * Sets VCM mode.
+ */
+ @NonNull
+ public Builder setVcmMode(@VcmMode int vcm) {
+ mVcmMode = vcm;
+ return this;
+ }
/**
* Builds a {@link DvbsFrontendSettings} object.
@@ -347,7 +384,7 @@
@NonNull
public DvbsFrontendSettings build() {
return new DvbsFrontendSettings(mFrequency, mModulation, mCoderate, mSymbolRate,
- mRolloff, mPilot, mInputStreamId, mStandard);
+ mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode);
}
@Override
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index f0469b7..9a82de0 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -110,7 +110,7 @@
*/
public static final int BANDWIDTH_5MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_5MHZ;
/**
- * 1.7 MHz bandwidth.
+ * 1,7 MHz bandwidth.
*/
public static final int BANDWIDTH_1_7MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_1_7MHZ;
/**
@@ -232,39 +232,39 @@
*/
public static final int CODERATE_AUTO = Constants.FrontendDvbtCoderate.AUTO;
/**
- * 1_2 code rate.
+ * 1/2 code rate.
*/
public static final int CODERATE_1_2 = Constants.FrontendDvbtCoderate.CODERATE_1_2;
/**
- * 2_3 code rate.
+ * 2/3 code rate.
*/
public static final int CODERATE_2_3 = Constants.FrontendDvbtCoderate.CODERATE_2_3;
/**
- * 3_4 code rate.
+ * 3/4 code rate.
*/
public static final int CODERATE_3_4 = Constants.FrontendDvbtCoderate.CODERATE_3_4;
/**
- * 5_6 code rate.
+ * 5/6 code rate.
*/
public static final int CODERATE_5_6 = Constants.FrontendDvbtCoderate.CODERATE_5_6;
/**
- * 7_8 code rate.
+ * 7/8 code rate.
*/
public static final int CODERATE_7_8 = Constants.FrontendDvbtCoderate.CODERATE_7_8;
/**
- * 4_5 code rate.
+ * 4/5 code rate.
*/
public static final int CODERATE_3_5 = Constants.FrontendDvbtCoderate.CODERATE_3_5;
/**
- * 4_5 code rate.
+ * 4/5 code rate.
*/
public static final int CODERATE_4_5 = Constants.FrontendDvbtCoderate.CODERATE_4_5;
/**
- * 6_7 code rate.
+ * 6/7 code rate.
*/
public static final int CODERATE_6_7 = Constants.FrontendDvbtCoderate.CODERATE_6_7;
/**
- * 8_9 code rate.
+ * 8/9 code rate.
*/
public static final int CODERATE_8_9 = Constants.FrontendDvbtCoderate.CODERATE_8_9;
diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
index 7e6f188..a83d771 100644
--- a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
@@ -87,47 +87,47 @@
*/
public static final int CODERATE_AUTO = Constants.FrontendIsdbs3Coderate.AUTO;
/**
- * 1_3 code rate.
+ * 1/3 code rate.
*/
public static final int CODERATE_1_3 = Constants.FrontendIsdbs3Coderate.CODERATE_1_3;
/**
- * 2_5 code rate.
+ * 2/5 code rate.
*/
public static final int CODERATE_2_5 = Constants.FrontendIsdbs3Coderate.CODERATE_2_5;
/**
- * 1_2 code rate.
+ * 1/2 code rate.
*/
public static final int CODERATE_1_2 = Constants.FrontendIsdbs3Coderate.CODERATE_1_2;
/**
- * 3_5 code rate.
+ * 3/5 code rate.
*/
public static final int CODERATE_3_5 = Constants.FrontendIsdbs3Coderate.CODERATE_3_5;
/**
- * 2_3 code rate.
+ * 2/3 code rate.
*/
public static final int CODERATE_2_3 = Constants.FrontendIsdbs3Coderate.CODERATE_2_3;
/**
- * 3_4 code rate.
+ * 3/4 code rate.
*/
public static final int CODERATE_3_4 = Constants.FrontendIsdbs3Coderate.CODERATE_3_4;
/**
- * 7_9 code rate.
+ * 7/9 code rate.
*/
public static final int CODERATE_7_9 = Constants.FrontendIsdbs3Coderate.CODERATE_7_9;
/**
- * 4_5 code rate.
+ * 4/5 code rate.
*/
public static final int CODERATE_4_5 = Constants.FrontendIsdbs3Coderate.CODERATE_4_5;
/**
- * 5_6 code rate.
+ * 5/6 code rate.
*/
public static final int CODERATE_5_6 = Constants.FrontendIsdbs3Coderate.CODERATE_5_6;
/**
- * 7_8 code rate.
+ * 7/8 code rate.
*/
public static final int CODERATE_7_8 = Constants.FrontendIsdbs3Coderate.CODERATE_7_8;
/**
- * 9_10 code rate.
+ * 9/10 code rate.
*/
public static final int CODERATE_9_10 = Constants.FrontendIsdbs3Coderate.CODERATE_9_10;
@@ -138,11 +138,11 @@
public @interface Rolloff {}
/**
- * Roll off type undefined.
+ * Rolloff type undefined.
*/
public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbs3Rolloff.UNDEFINED;
/**
- * 0.03 roll off type.
+ * 0,03 Rolloff.
*/
public static final int ROLLOFF_0_03 = Constants.FrontendIsdbs3Rolloff.ROLLOFF_0_03;
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
index fe100f8..bb809bf 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
@@ -96,23 +96,23 @@
*/
public static final int CODERATE_AUTO = Constants.FrontendIsdbsCoderate.AUTO;
/**
- * 1_2 code rate.
+ * 1/2 code rate.
*/
public static final int CODERATE_1_2 = Constants.FrontendIsdbsCoderate.CODERATE_1_2;
/**
- * 2_3 code rate.
+ * 2/3 code rate.
*/
public static final int CODERATE_2_3 = Constants.FrontendIsdbsCoderate.CODERATE_2_3;
/**
- * 3_4 code rate.
+ * 3/4 code rate.
*/
public static final int CODERATE_3_4 = Constants.FrontendIsdbsCoderate.CODERATE_3_4;
/**
- * 5_6 code rate.
+ * 5/6 code rate.
*/
public static final int CODERATE_5_6 = Constants.FrontendIsdbsCoderate.CODERATE_5_6;
/**
- * 7_8 code rate.
+ * 7/8 code rate.
*/
public static final int CODERATE_7_8 = Constants.FrontendIsdbsCoderate.CODERATE_7_8;
@@ -123,11 +123,11 @@
public @interface Rolloff {}
/**
- * Roll off type undefined.
+ * Rolloff type undefined.
*/
public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbs3Rolloff.UNDEFINED;
/**
- * 0.35 roll off type.
+ * 0,35 rolloff.
*/
public static final int ROLLOFF_0_35 = Constants.FrontendIsdbsRolloff.ROLLOFF_0_35;
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
index 5e7d218..0479e55 100644
--- a/media/java/android/media/tv/tuner/frontend/ScanCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -16,6 +16,7 @@
package android.media.tv.tuner.frontend;
+
/**
* Scan callback.
*
@@ -31,11 +32,11 @@
/** scan progress percent (0..100) */
void onProgress(int percent);
- /** Signal frequency in Hertz */
- void onFrequencyReport(int frequency);
+ /** Signal frequencies in Hertz */
+ void onFrequenciesReport(int[] frequency);
/** Symbols per second */
- void onSymbolRate(int rate);
+ void onSymbolRates(int[] rate);
/** Locked Plp Ids for DVBT2 frontend. */
void onPlpIds(int[] plpIds);
@@ -46,15 +47,24 @@
/** Stream Ids. */
void onInputStreamIds(int[] inputStreamIds);
- /** Locked signal standard. */
+ /** Locked signal standard for DVBS. */
void onDvbsStandard(@DvbsFrontendSettings.Standard int dvbsStandandard);
- /** Locked signal standard. */
+ /** Locked signal standard. for DVBT */
void onDvbtStandard(@DvbtFrontendSettings.Standard int dvbtStandard);
+ /** Locked signal SIF standard for Analog. */
+ void onAnalogSifStandard(@AnalogFrontendSettings.SifStandard int sif);
+
/** PLP status in a tuned frequency band for ATSC3 frontend. */
void onAtsc3PlpInfos(Atsc3PlpInfo[] atsc3PlpInfos);
+ /** Frontend hierarchy. */
+ void onHierarchy(@DvbtFrontendSettings.Hierarchy int hierarchy);
+
+ /** Frontend hierarchy. */
+ void onSignalType(@AnalogFrontendSettings.SignalType int signalType);
+
/** PLP information for ATSC3. */
class Atsc3PlpInfo {
private final int mPlpId;
diff --git a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
index f04226e..cd90efe 100644
--- a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
+++ b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
@@ -32,8 +32,8 @@
android:orientation="horizontal">
<FrameLayout
- android:layout_width="90dp"
- android:layout_height="94dp">
+ android:layout_width="45dp"
+ android:layout_height="47dp">
<View
android:id="@+id/icon_container_bg"
@@ -43,35 +43,34 @@
<FrameLayout
android:id="@+id/icon_mic"
- android:layout_width="70dp"
- android:layout_height="70dp"
- android:layout_marginLeft="12dp"
- android:layout_marginTop="12dp"
- android:layout_marginRight="8dp"
- android:layout_marginBottom="12dp">
+ android:layout_width="35dp"
+ android:layout_height="35dp"
+ android:layout_marginLeft="6dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp">
<View
- android:layout_width="54dp"
- android:layout_height="54dp"
+ android:layout_width="27dp"
+ android:layout_height="27dp"
android:layout_gravity="center"
android:background="@drawable/tv_circle_dark"/>
<ImageView
android:id="@+id/pulsating_circle"
- android:layout_width="54dp"
- android:layout_height="54dp"
+ android:layout_width="27dp"
+ android:layout_height="27dp"
android:layout_gravity="center"
android:background="@drawable/tv_circle_white_translucent"/>
<ImageView
- android:layout_width="54dp"
- android:layout_height="54dp"
+ android:layout_width="27dp"
+ android:layout_height="27dp"
android:layout_gravity="center"
android:src="@drawable/tv_ring_white"/>
<ImageView
- android:layout_width="32dp"
- android:layout_height="32dp"
+ android:layout_width="16dp"
+ android:layout_height="16dp"
android:layout_gravity="center"
android:background="@drawable/tv_ic_mic_white"/>
</FrameLayout>
@@ -81,29 +80,30 @@
<LinearLayout
android:id="@+id/texts_container"
android:layout_width="wrap_content"
- android:layout_height="94dp"
+ android:layout_height="47dp"
android:background="@color/tv_audio_recording_indicator_background"
- android:gravity="center_vertical"
android:orientation="vertical"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="14dp"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="1dp"
android:text="@string/mic_active"
android:textColor="@android:color/white"
android:fontFamily="sans-serif"
- android:textSize="20dp"/>
+ android:textSize="10dp"/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="14dp"
android:singleLine="true"
android:text="SomeApplication accessed your microphone"
android:textColor="@android:color/white"
android:fontFamily="sans-serif"
- android:textSize="16dp"/>
+ android:textSize="8dp"/>
</LinearLayout>
@@ -113,8 +113,8 @@
<View
android:id="@+id/bg_right"
- android:layout_width="24dp"
- android:layout_height="94dp"
+ android:layout_width="12dp"
+ android:layout_height="47dp"
android:background="@drawable/tv_rect_dark_right_rounded"
android:visibility="visible"/>
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 895207d..898cd13 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -17,6 +17,8 @@
package com.android.systemui.accessibility;
import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings;
@@ -35,10 +37,25 @@
private WindowMagnificationController mWindowMagnificationController;
private final Handler mHandler;
+ private Configuration mLastConfiguration;
+
@Inject
public WindowMagnification(Context context, @Main Handler mainHandler) {
super(context);
mHandler = mainHandler;
+ mLastConfiguration = new Configuration(context.getResources().getConfiguration());
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ final int configDiff = newConfig.diff(mLastConfiguration);
+ if ((configDiff & ActivityInfo.CONFIG_DENSITY) == 0) {
+ return;
+ }
+ mLastConfiguration.setTo(newConfig);
+ if (mWindowMagnificationController != null) {
+ mWindowMagnificationController.onConfigurationChanged(configDiff);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index bfac4fc..c243309 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -113,6 +113,7 @@
if (mMirrorView != null) {
return;
}
+ setInitialStartBounds();
createOverlayWindow();
}
@@ -178,9 +179,20 @@
}
}
- private void createMirrorWindow() {
- setInitialStartBounds();
+ /**
+ * Called when the configuration has changed, and it updates window magnification UI.
+ *
+ * @param configDiff a bit mask of the differences between the configurations
+ */
+ void onConfigurationChanged(int configDiff) {
+ // TODO(b/145780606): update toggle button UI.
+ if (mMirrorView != null) {
+ mWm.removeView(mMirrorView);
+ createMirrorWindow();
+ }
+ }
+ private void createMirrorWindow() {
// The window should be the size the mirrored surface will be but also add room for the
// border and the drag handle.
int dragViewHeight = (int) mContext.getResources().getDimension(
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index c9fdd5a..f3a415e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -94,6 +94,7 @@
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityManager;
import android.view.accessibility.IAccessibilityManagerClient;
+import android.view.accessibility.IWindowMagnificationConnection;
import com.android.internal.R;
import com.android.internal.accessibility.AccessibilityShortcutController;
@@ -106,6 +107,7 @@
import com.android.internal.util.IntPair;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.accessibility.magnification.WindowMagnificationManager;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -204,6 +206,8 @@
private AccessibilityInputFilter mInputFilter;
+ private WindowMagnificationManager mWindowMagnificationMgr;
+
private boolean mHasInputFilter;
private KeyEventDispatcher mKeyEventDispatcher;
@@ -877,11 +881,8 @@
*/
@Override
public void notifyAccessibilityButtonVisibilityChanged(boolean shown) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Caller does not hold permission "
- + android.Manifest.permission.STATUS_BAR_SERVICE);
- }
+ mSecurityPolicy.enforceCallingOrSelfPermission(
+ android.Manifest.permission.STATUS_BAR_SERVICE);
synchronized (mLock) {
notifyAccessibilityButtonVisibilityChangedLocked(shown);
}
@@ -1883,11 +1884,12 @@
}
private boolean readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState) {
+ final String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userState.mUserId);
final Set<String> targetsFromSetting = new ArraySet<>();
- readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
- userState.mUserId, targetsFromSetting, str -> str);
- if (targetsFromSetting.isEmpty()) {
- // Fall back to device's default a11y service.
+ readColonDelimitedStringToSet(settingValue, targetsFromSetting, false, str -> str);
+ // Fall back to device's default a11y service, only when setting is never updated.
+ if (settingValue == null) {
final String defaultService = mContext.getString(
R.string.config_defaultAccessibilityService);
if (!TextUtils.isEmpty(defaultService)) {
@@ -2588,6 +2590,24 @@
}
@Override
+ public void setWindowMagnificationConnection(
+ IWindowMagnificationConnection connection) throws RemoteException {
+ mSecurityPolicy.enforceCallingOrSelfPermission(
+ android.Manifest.permission.STATUS_BAR_SERVICE);
+
+ getWindowMagnificationMgr().setConnection(connection);
+ }
+
+ WindowMagnificationManager getWindowMagnificationMgr() {
+ synchronized (mLock) {
+ if (mWindowMagnificationMgr == null) {
+ mWindowMagnificationMgr = new WindowMagnificationManager();
+ }
+ return mWindowMagnificationMgr;
+ }
+ }
+
+ @Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
synchronized (mLock) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
index 7dbec7c..7a42cd1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
@@ -550,4 +550,17 @@
Binder.restoreCallingIdentity(identityToken);
}
}
+
+ /**
+ * Enforcing permission check to IPC caller or grant it if it's not through IPC.
+ *
+ * @param permission The permission to check
+ */
+ public void enforceCallingOrSelfPermission(@NonNull String permission) {
+ if (mContext.checkCallingOrSelfPermission(permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller does not hold permission "
+ + permission);
+ }
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java
new file mode 100644
index 0000000..351c9e0
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+import static android.os.IBinder.DeathRecipient;
+
+import android.annotation.NonNull;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.accessibility.IWindowMagnificationConnection;
+import android.view.accessibility.IWindowMagnificationConnectionCallback;
+
+/**
+ * A wrapper of {@link IWindowMagnificationConnection}.
+ */
+class WindowMagnificationConnectionWrapper {
+
+ private static final boolean DBG = false;
+ private static final String TAG = "WindowMagnificationConnectionWrapper";
+
+ private final @NonNull IWindowMagnificationConnection mConnection;
+
+ WindowMagnificationConnectionWrapper(@NonNull IWindowMagnificationConnection connection) {
+ mConnection = connection;
+ }
+
+ //Should not use this instance anymore after calling it.
+ void unlinkToDeath(@NonNull DeathRecipient deathRecipient) {
+ mConnection.asBinder().unlinkToDeath(deathRecipient, 0);
+ }
+
+ void linkToDeath(@NonNull DeathRecipient deathRecipient) throws RemoteException {
+ mConnection.asBinder().linkToDeath(deathRecipient, 0);
+ }
+
+ boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY) {
+ try {
+ mConnection.enableWindowMagnification(displayId, scale, centerX, centerY);
+ } catch (RemoteException e) {
+ if (DBG) {
+ Slog.e(TAG, "Error calling enableWindowMagnification()");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ boolean setScale(int displayId, float scale) {
+ try {
+ mConnection.setScale(displayId, scale);
+ } catch (RemoteException e) {
+ if (DBG) {
+ Slog.e(TAG, "Error calling setScale()");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ boolean disableWindowMagnification(int displayId) {
+ try {
+ mConnection.disableWindowMagnification(displayId);
+ } catch (RemoteException e) {
+ if (DBG) {
+ Slog.e(TAG, "Error calling disableWindowMagnification()");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ boolean moveWindowMagnifier(int displayId, float offsetX, float offsetY) {
+ try {
+ mConnection.moveWindowMagnifier(displayId, offsetX, offsetY);
+ } catch (RemoteException e) {
+ if (DBG) {
+ Slog.e(TAG, "Error calling moveWindowMagnifier()");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ boolean setConnectionCallback(IWindowMagnificationConnectionCallback connectionCallback) {
+ try {
+ mConnection.setConnectionCallback(connectionCallback);
+ } catch (RemoteException e) {
+ if (DBG) {
+ Slog.e(TAG, "Error calling setConnectionCallback()");
+ }
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
new file mode 100644
index 0000000..00db329
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.accessibility.IWindowMagnificationConnection;
+import android.view.accessibility.IWindowMagnificationConnectionCallback;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A class to manipulate window magnification through {@link WindowMagnificationConnectionWrapper}.
+ */
+public final class WindowMagnificationManager {
+
+ private static final String TAG = "WindowMagnificationMgr";
+ private final Object mLock = new Object();
+ @VisibleForTesting
+ @Nullable WindowMagnificationConnectionWrapper mConnectionWrapper;
+ private ConnectionCallback mConnectionCallback;
+
+ /**
+ * Sets {@link IWindowMagnificationConnection}.
+ * @param connection {@link IWindowMagnificationConnection}
+ */
+ public void setConnection(@Nullable IWindowMagnificationConnection connection) {
+ synchronized (mLock) {
+ //Reset connectionWrapper.
+ if (mConnectionWrapper != null) {
+ mConnectionWrapper.setConnectionCallback(null);
+ if (mConnectionCallback != null) {
+ mConnectionCallback.mExpiredDeathRecipient = true;
+ }
+ mConnectionWrapper.unlinkToDeath(mConnectionCallback);
+ mConnectionWrapper = null;
+ }
+ if (connection != null) {
+ mConnectionWrapper = new WindowMagnificationConnectionWrapper(connection);
+ }
+
+ if (mConnectionWrapper != null) {
+ try {
+ mConnectionCallback = new ConnectionCallback();
+ mConnectionWrapper.linkToDeath(mConnectionCallback);
+ mConnectionWrapper.setConnectionCallback(mConnectionCallback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "setConnection failed", e);
+ mConnectionWrapper = null;
+ }
+ }
+ }
+ }
+
+ private class ConnectionCallback extends IWindowMagnificationConnectionCallback.Stub implements
+ IBinder.DeathRecipient {
+ private boolean mExpiredDeathRecipient = false;
+
+ @Override
+ public void onWindowMagnifierBoundsChanged(int display, Rect frame) throws RemoteException {
+ }
+
+ @Override
+ public void onChangeMagnificationMode(int display, int magnificationMode)
+ throws RemoteException {
+ }
+
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ if (mExpiredDeathRecipient) {
+ Slog.w(TAG, "binderDied DeathRecipient is expired");
+ return;
+ }
+ mConnectionWrapper.unlinkToDeath(this);
+ mConnectionWrapper = null;
+ mConnectionCallback = null;
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index c1e23e4..5e495b9 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -39,6 +39,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.uidRulesToString;
@@ -5840,11 +5841,6 @@
} else {
newNc.addCapability(NET_CAPABILITY_FOREGROUND);
}
- if (nai.isSuspended()) {
- newNc.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
- } else {
- newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
- }
if (nai.partialConnectivity) {
newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
} else {
@@ -5852,6 +5848,11 @@
}
newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken());
+ // TODO : remove this once all factories are updated to send NOT_SUSPENDED
+ if (!newNc.hasTransport(TRANSPORT_CELLULAR)) {
+ newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ }
+
return newNc;
}
@@ -5896,6 +5897,17 @@
// on this network. We might have been called by rematchNetworkAndRequests when a
// network changed foreground state.
processListenRequests(nai);
+ final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ if (prevSuspended != suspended) {
+ // TODO (b/73132094) : remove this call once the few users of onSuspended and
+ // onResumed have been removed.
+ notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED
+ : ConnectivityManager.CALLBACK_RESUMED);
+ // updateNetworkInfo will mix in the suspended info from the capabilities and
+ // take appropriate action for the network having possibly changed state.
+ updateNetworkInfo(nai, nai.networkInfo);
+ }
} else {
// If the requestable capabilities have changed or the score changed, we can't have been
// called by rematchNetworkAndRequests, so it's safe to start a rematch.
@@ -5903,6 +5915,9 @@
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
+ // TODO : static analysis indicates that prevNc can't be null here (getAndSetNetworkCaps
+ // never returns null), so mark the relevant members and functions in nai as @NonNull and
+ // remove this test
if (prevNc != null) {
final boolean oldMetered = prevNc.isMetered();
final boolean newMetered = newNc.isMetered();
@@ -6597,10 +6612,30 @@
}
}
- private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
+ @NonNull
+ private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) {
+ final NetworkInfo newInfo = new NetworkInfo(info);
+ // The suspended bit is managed in NetworkCapabilities.
+ final boolean suspended =
+ !nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
+ // Only override the state with SUSPENDED if the network is currently in CONNECTED
+ // state. This is because the network could have been suspended before connecting,
+ // or it could be disconnecting while being suspended, and in both these cases
+ // the state should not be overridden. Note that the only detailed state that
+ // maps to State.CONNECTED is DetailedState.CONNECTED, so there is also no need to
+ // worry about multiple different substates of CONNECTED.
+ newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(),
+ info.getExtraInfo());
+ }
+ return newInfo;
+ }
+
+ private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info) {
+ final NetworkInfo newInfo = mixInInfo(networkAgent, info);
+
final NetworkInfo.State state = newInfo.getState();
NetworkInfo oldInfo = null;
- final int oldScore = networkAgent.getCurrentScore();
synchronized (networkAgent) {
oldInfo = networkAgent.networkInfo;
networkAgent.networkInfo = newInfo;
@@ -6682,17 +6717,6 @@
}
} else if (networkAgent.created && (oldInfo.getState() == NetworkInfo.State.SUSPENDED ||
state == NetworkInfo.State.SUSPENDED)) {
- // going into or coming out of SUSPEND: re-score and notify
- if (networkAgent.getCurrentScore() != oldScore) {
- rematchAllNetworksAndRequests();
- }
- updateCapabilities(networkAgent.getCurrentScore(), networkAgent,
- networkAgent.networkCapabilities);
- // TODO (b/73132094) : remove this call once the few users of onSuspended and
- // onResumed have been removed.
- notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ?
- ConnectivityManager.CALLBACK_SUSPENDED :
- ConnectivityManager.CALLBACK_RESUMED));
mLegacyTypeTracker.update(networkAgent);
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index c1ab551..d66aec5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -451,15 +451,6 @@
&& !isLingering();
}
- /**
- * Returns whether this network is currently suspended. A network is suspended if it is still
- * connected but data temporarily fails to transfer. See {@link NetworkInfo.State#SUSPENDED}
- * and {@link NetworkCapabilities#NET_CAPABILITY_NOT_SUSPENDED}.
- */
- public boolean isSuspended() {
- return networkInfo.getState() == NetworkInfo.State.SUSPENDED;
- }
-
// Does this network satisfy request?
public boolean satisfies(NetworkRequest request) {
return created &&
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 6331dd4..b1c38d1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -400,10 +400,10 @@
} finally {
IoUtils.closeQuietly(fis);
}
- // After all of the sessions were loaded, they are ready to be sealed and validated
+ // Re-sealing the sealed sessions.
for (int i = 0; i < mSessions.size(); ++i) {
PackageInstallerSession session = mSessions.valueAt(i);
- session.sealAndValidateIfNecessary();
+ session.sealIfNecessary();
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 165bdeb..71555c9 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1374,15 +1374,13 @@
}
/**
- * If session should be sealed, then it's sealed to prevent further modification
- * and then it's validated.
- *
- * If the session was sealed but something went wrong then it's destroyed.
+ * If session should be sealed, then it's sealed to prevent further modification.
+ * If the session can't be sealed then it's destroyed.
*
* <p> This is meant to be called after all of the sessions are loaded and added to
* PackageInstallerService
*/
- void sealAndValidateIfNecessary() {
+ void sealIfNecessary() {
synchronized (mLock) {
if (!mShouldBeSealed || isStagedAndInTerminalState()) {
return;
@@ -1391,9 +1389,7 @@
List<PackageInstallerSession> childSessions = getChildSessions();
synchronized (mLock) {
try {
- sealAndValidateLocked(childSessions);
- } catch (StreamingException e) {
- Slog.e(TAG, "Streaming failed", e);
+ sealLocked(childSessions);
} catch (PackageManagerException e) {
Slog.e(TAG, "Package not valid", e);
}
diff --git a/services/core/java/com/android/server/stats/IonMemoryUtil.java b/services/core/java/com/android/server/stats/pull/IonMemoryUtil.java
similarity index 93%
rename from services/core/java/com/android/server/stats/IonMemoryUtil.java
rename to services/core/java/com/android/server/stats/pull/IonMemoryUtil.java
index c9be96f..fde0a59 100644
--- a/services/core/java/com/android/server/stats/IonMemoryUtil.java
+++ b/services/core/java/com/android/server/stats/pull/IonMemoryUtil.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.stats;
+package com.android.server.stats.pull;
import android.os.FileUtils;
import android.util.Slog;
@@ -30,8 +30,11 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/** Utility methods for reading ion memory stats. */
-final class IonMemoryUtil {
+/**
+ * Utility methods for reading ion memory stats.
+ * TODO: Consider making package private after puller migration
+ */
+public final class IonMemoryUtil {
private static final String TAG = "IonMemoryUtil";
/** Path to debugfs file for the system ion heap. */
@@ -50,7 +53,7 @@
* Returns value of the total size in bytes of the system ion heap from
* /sys/kernel/debug/ion/heaps/system.
*/
- static long readSystemIonHeapSizeFromDebugfs() {
+ public static long readSystemIonHeapSizeFromDebugfs() {
return parseIonHeapSizeFromDebugfs(readFile(DEBUG_SYSTEM_ION_HEAP_FILE));
}
@@ -78,7 +81,7 @@
* Returns values of allocation sizes in bytes on the system ion heap from
* /sys/kernel/debug/ion/heaps/system.
*/
- static List<IonAllocations> readProcessSystemIonHeapSizesFromDebugfs() {
+ public static List<IonAllocations> readProcessSystemIonHeapSizesFromDebugfs() {
return parseProcessIonHeapSizesFromDebugfs(readFile(DEBUG_SYSTEM_ION_HEAP_FILE));
}
@@ -130,7 +133,7 @@
}
/** Summary information about process ion allocations. */
- static final class IonAllocations {
+ public static final class IonAllocations {
/** PID these allocations belong to. */
public int pid;
/** Size of all individual allocations added together. */
diff --git a/services/core/java/com/android/server/stats/ProcfsMemoryUtil.java b/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
similarity index 89%
rename from services/core/java/com/android/server/stats/ProcfsMemoryUtil.java
rename to services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
index c1eacce..638dfd2 100644
--- a/services/core/java/com/android/server/stats/ProcfsMemoryUtil.java
+++ b/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.stats;
+package com.android.server.stats.pull;
import static android.os.Process.PROC_OUT_STRING;
@@ -22,7 +22,7 @@
import java.util.function.BiConsumer;
-final class ProcfsMemoryUtil {
+public final class ProcfsMemoryUtil {
private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING };
private static final String[] STATUS_KEYS = new String[] {
"Uid:",
@@ -39,7 +39,7 @@
* VmSwap fields in /proc/pid/status in kilobytes or null if not available.
*/
@Nullable
- static MemorySnapshot readMemorySnapshotFromProcfs(int pid) {
+ public static MemorySnapshot readMemorySnapshotFromProcfs(int pid) {
long[] output = new long[STATUS_KEYS.length];
output[0] = -1;
Process.readProcLines("/proc/" + pid + "/status", STATUS_KEYS, output);
@@ -63,7 +63,7 @@
* Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
* if the file is not available.
*/
- static String readCmdlineFromProcfs(int pid) {
+ public static String readCmdlineFromProcfs(int pid) {
String[] cmdline = new String[1];
if (!Process.readProcFile("/proc/" + pid + "/cmdline", CMDLINE_OUT, cmdline, null, null)) {
return "";
@@ -71,7 +71,7 @@
return cmdline[0];
}
- static void forEachPid(BiConsumer<Integer, String> func) {
+ public static void forEachPid(BiConsumer<Integer, String> func) {
int[] pids = new int[1024];
pids = Process.getPids("/proc", pids);
for (int pid : pids) {
@@ -86,7 +86,7 @@
}
}
- static final class MemorySnapshot {
+ public static final class MemorySnapshot {
public int uid;
public int rssHighWaterMarkInKilobytes;
public int rssInKilobytes;
diff --git a/services/core/java/com/android/server/stats/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
similarity index 74%
rename from services/core/java/com/android/server/stats/StatsPullAtomService.java
rename to services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index f78330e..3bc860a 100644
--- a/services/core/java/com/android/server/stats/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.stats;
+package com.android.server.stats.pull;
import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
@@ -26,11 +26,11 @@
import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static com.android.server.stats.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
-import static com.android.server.stats.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
-import static com.android.server.stats.ProcfsMemoryUtil.forEachPid;
-import static com.android.server.stats.ProcfsMemoryUtil.readCmdlineFromProcfs;
-import static com.android.server.stats.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
+import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
+import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
+import static com.android.server.stats.pull.ProcfsMemoryUtil.forEachPid;
+import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
+import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -142,8 +142,8 @@
import com.android.server.am.MemoryStatUtil.MemoryStat;
import com.android.server.notification.NotificationManagerService;
import com.android.server.role.RoleManagerInternal;
-import com.android.server.stats.IonMemoryUtil.IonAllocations;
-import com.android.server.stats.ProcfsMemoryUtil.MemorySnapshot;
+import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
+import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
import com.android.server.storage.DiskStatsFileLogger;
import com.android.server.storage.DiskStatsLoggingService;
@@ -270,8 +270,8 @@
registerProcessSystemIonHeapSize();
registerTemperature();
registerCoolingDevice();
- registerBinderCalls();
- registerBinderCallsExceptions();
+ registerBinderCallsStats();
+ registerBinderCallsStatsExceptions();
registerLooperStats();
registerDiskStats();
registerDirectoryUsage();
@@ -1004,35 +1004,227 @@
}
private void registerProcessMemoryState() {
- // No op.
+ int tagId = StatsLog.PROCESS_MEMORY_STATE;
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+ .setAdditiveFields(new int[] {4, 5, 6, 7, 8})
+ .build();
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ metadata,
+ (atomTag, data) -> pullProcessMemoryState(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullProcessMemoryState() {
- // No op.
+ private int pullProcessMemoryState(int atomTag, List<StatsEvent> pulledData) {
+ List<ProcessMemoryState> processMemoryStates =
+ LocalServices.getService(ActivityManagerInternal.class)
+ .getMemoryStateForProcesses();
+ for (ProcessMemoryState processMemoryState : processMemoryStates) {
+ final MemoryStat memoryStat = readMemoryStatFromFilesystem(processMemoryState.uid,
+ processMemoryState.pid);
+ if (memoryStat == null) {
+ continue;
+ }
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(processMemoryState.uid)
+ .writeString(processMemoryState.processName)
+ .writeInt(processMemoryState.oomScore)
+ .writeLong(memoryStat.pgfault)
+ .writeLong(memoryStat.pgmajfault)
+ .writeLong(memoryStat.rssInBytes)
+ .writeLong(memoryStat.cacheInBytes)
+ .writeLong(memoryStat.swapInBytes)
+ .writeLong(-1) // unused
+ .writeLong(-1) // unused
+ .writeInt(-1) // unused
+ .build();
+ pulledData.add(e);
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ /**
+ * Which native processes to snapshot memory for.
+ *
+ * <p>Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns
+ * /system/bin/statsd for the stats daemon.
+ */
+ private static final Set<String> MEMORY_INTERESTING_NATIVE_PROCESSES = Sets.newHashSet(
+ "/system/bin/statsd", // Stats daemon.
+ "/system/bin/surfaceflinger",
+ "/system/bin/apexd", // APEX daemon.
+ "/system/bin/audioserver",
+ "/system/bin/cameraserver",
+ "/system/bin/drmserver",
+ "/system/bin/healthd",
+ "/system/bin/incidentd",
+ "/system/bin/installd",
+ "/system/bin/lmkd", // Low memory killer daemon.
+ "/system/bin/logd",
+ "media.codec",
+ "media.extractor",
+ "media.metrics",
+ "/system/bin/mediadrmserver",
+ "/system/bin/mediaserver",
+ "/system/bin/performanced",
+ "/system/bin/tombstoned",
+ "/system/bin/traced", // Perfetto.
+ "/system/bin/traced_probes", // Perfetto.
+ "webview_zygote",
+ "zygote",
+ "zygote64");
+
+ /**
+ * Lowest available uid for apps.
+ *
+ * <p>Used to quickly discard memory snapshots of the zygote forks from native process
+ * measurements.
+ */
+ private static final int MIN_APP_UID = 10_000;
+
+ private static boolean isAppUid(int uid) {
+ return uid >= MIN_APP_UID;
}
private void registerProcessMemoryHighWaterMark() {
- // No op.
+ int tagId = StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ (atomTag, data) -> pullProcessMemoryHighWaterMark(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullProcessMemoryHighWaterMark() {
- // No op.
+ private int pullProcessMemoryHighWaterMark(int atomTag, List<StatsEvent> pulledData) {
+ List<ProcessMemoryState> managedProcessList =
+ LocalServices.getService(ActivityManagerInternal.class)
+ .getMemoryStateForProcesses();
+ for (ProcessMemoryState managedProcess : managedProcessList) {
+ final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
+ if (snapshot == null) {
+ continue;
+ }
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(managedProcess.uid)
+ .writeString(managedProcess.processName)
+ // RSS high-water mark in bytes.
+ .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L)
+ .writeInt(snapshot.rssHighWaterMarkInKilobytes)
+ .build();
+ pulledData.add(e);
+ }
+ forEachPid((pid, cmdLine) -> {
+ if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
+ return;
+ }
+ final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
+ if (snapshot == null) {
+ return;
+ }
+ // Sometimes we get here a process that is not included in the whitelist. It comes
+ // from forking the zygote for an app. We can ignore that sample because this process
+ // is collected by ProcessMemoryState.
+ if (isAppUid(snapshot.uid)) {
+ return;
+ }
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(snapshot.uid)
+ .writeString(cmdLine)
+ // RSS high-water mark in bytes.
+ .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L)
+ .writeInt(snapshot.rssHighWaterMarkInKilobytes)
+ .build();
+ pulledData.add(e);
+ });
+ // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes.
+ SystemProperties.set("sys.rss_hwm_reset.on", "1");
+ return StatsManager.PULL_SUCCESS;
}
private void registerProcessMemorySnapshot() {
- // No op.
+ int tagId = StatsLog.PROCESS_MEMORY_SNAPSHOT;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ (atomTag, data) -> pullProcessMemorySnapshot(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullProcessMemorySnapshot() {
- // No op.
+ private int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
+ List<ProcessMemoryState> managedProcessList =
+ LocalServices.getService(ActivityManagerInternal.class)
+ .getMemoryStateForProcesses();
+ for (ProcessMemoryState managedProcess : managedProcessList) {
+ final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
+ if (snapshot == null) {
+ continue;
+ }
+ StatsEvent e = StatsEvent.newBuilder()
+ .writeInt(managedProcess.uid)
+ .writeString(managedProcess.processName)
+ .writeInt(managedProcess.pid)
+ .writeInt(managedProcess.oomScore)
+ .writeInt(snapshot.rssInKilobytes)
+ .writeInt(snapshot.anonRssInKilobytes)
+ .writeInt(snapshot.swapInKilobytes)
+ .writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes)
+ .build();
+ pulledData.add(e);
+ }
+ forEachPid((pid, cmdLine) -> {
+ if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) {
+ return;
+ }
+ final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid);
+ if (snapshot == null) {
+ return;
+ }
+ // Sometimes we get here a process that is not included in the whitelist. It comes
+ // from forking the zygote for an app. We can ignore that sample because this process
+ // is collected by ProcessMemoryState.
+ if (isAppUid(snapshot.uid)) {
+ return;
+ }
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(snapshot.uid)
+ .writeString(cmdLine)
+ .writeInt(pid)
+ .writeInt(-1001) // Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.
+ .writeInt(snapshot.rssInKilobytes)
+ .writeInt(snapshot.anonRssInKilobytes)
+ .writeInt(snapshot.swapInKilobytes)
+ .writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes)
+ .build();
+ pulledData.add(e);
+ });
+ return StatsManager.PULL_SUCCESS;
}
private void registerSystemIonHeapSize() {
- // No op.
+ int tagId = StatsLog.SYSTEM_ION_HEAP_SIZE;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ (atomTag, data) -> pullSystemIonHeapSize(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullSystemIonHeapSize() {
- // No op.
+ private int pullSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+ final long systemIonHeapSizeInBytes = readSystemIonHeapSizeFromDebugfs();
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeLong(systemIonHeapSizeInBytes)
+ .build();
+ pulledData.add(e);
+ return StatsManager.PULL_SUCCESS;
}
private void registerIonHeapSize() {
@@ -1056,43 +1248,182 @@
}
private void registerProcessSystemIonHeapSize() {
- // No op.
+ int tagId = StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ (atomTag, data) -> pullProcessSystemIonHeapSize(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullProcessSystemIonHeapSize() {
- // No op.
+ private int pullProcessSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+ List<IonAllocations> result = readProcessSystemIonHeapSizesFromDebugfs();
+ for (IonAllocations allocations : result) {
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(getUidForPid(allocations.pid))
+ .writeString(readCmdlineFromProcfs(allocations.pid))
+ .writeInt((int) (allocations.totalSizeInBytes / 1024))
+ .writeInt(allocations.count)
+ .writeInt((int) (allocations.maxSizeInBytes / 1024))
+ .build();
+ pulledData.add(e);
+ }
+ return StatsManager.PULL_SUCCESS;
}
private void registerTemperature() {
- // No op.
+ int tagId = StatsLog.TEMPERATURE;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ (atomTag, data) -> pullTemperature(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullTemperature() {
- // No op.
+ private int pullTemperature(int atomTag, List<StatsEvent> pulledData) {
+ IThermalService thermalService = getIThermalService();
+ if (thermalService == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ List<Temperature> temperatures = thermalService.getCurrentTemperatures();
+ for (Temperature temp : temperatures) {
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(temp.getType())
+ .writeString(temp.getName())
+ .writeInt((int) (temp.getValue() * 10))
+ .writeInt(temp.getStatus())
+ .build();
+ pulledData.add(e);
+ }
+ } catch (RemoteException e) {
+ // Should not happen.
+ Slog.e(TAG, "Disconnected from thermal service. Cannot pull temperatures.");
+ return StatsManager.PULL_SKIP;
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ return StatsManager.PULL_SUCCESS;
}
private void registerCoolingDevice() {
- // No op.
+ int tagId = StatsLog.COOLING_DEVICE;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ (atomTag, data) -> pullCooldownDevice(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullCooldownDevice() {
- // No op.
+ private int pullCooldownDevice(int atomTag, List<StatsEvent> pulledData) {
+ IThermalService thermalService = getIThermalService();
+ if (thermalService == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ List<CoolingDevice> devices = thermalService.getCurrentCoolingDevices();
+ for (CoolingDevice device : devices) {
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(device.getType())
+ .writeString(device.getName())
+ .writeInt((int) (device.getValue()))
+ .build();
+ pulledData.add(e);
+ }
+ } catch (RemoteException e) {
+ // Should not happen.
+ Slog.e(TAG, "Disconnected from thermal service. Cannot pull temperatures.");
+ return StatsManager.PULL_SKIP;
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ return StatsManager.PULL_SUCCESS;
}
- private void registerBinderCalls() {
- // No op.
+ private void registerBinderCallsStats() {
+ int tagId = StatsLog.BINDER_CALLS;
+ PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+ .setAdditiveFields(new int[] {4, 5, 6, 8, 12})
+ .build();
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ metadata,
+ (atomTag, data) -> pullBinderCallsStats(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullBinderCalls() {
- // No op.
+ private int pullBinderCallsStats(int atomTag, List<StatsEvent> pulledData) {
+ BinderCallsStatsService.Internal binderStats =
+ LocalServices.getService(BinderCallsStatsService.Internal.class);
+ if (binderStats == null) {
+ Slog.e(TAG, "failed to get binderStats");
+ return StatsManager.PULL_SKIP;
+ }
+
+ List<ExportedCallStat> callStats = binderStats.getExportedCallStats();
+ binderStats.reset();
+ for (ExportedCallStat callStat : callStats) {
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(callStat.workSourceUid)
+ .writeString(callStat.className)
+ .writeString(callStat.methodName)
+ .writeLong(callStat.callCount)
+ .writeLong(callStat.exceptionCount)
+ .writeLong(callStat.latencyMicros)
+ .writeLong(callStat.maxLatencyMicros)
+ .writeLong(callStat.cpuTimeMicros)
+ .writeLong(callStat.maxCpuTimeMicros)
+ .writeLong(callStat.maxReplySizeBytes)
+ .writeLong(callStat.maxRequestSizeBytes)
+ .writeLong(callStat.recordedCallCount)
+ .writeInt(callStat.screenInteractive ? 1 : 0)
+ .writeInt(callStat.callingUid)
+ .build();
+ pulledData.add(e);
+ }
+ return StatsManager.PULL_SUCCESS;
}
- private void registerBinderCallsExceptions() {
- // No op.
+ private void registerBinderCallsStatsExceptions() {
+ int tagId = StatsLog.BINDER_CALLS_EXCEPTIONS;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ (atomTag, data) -> pullBinderCallsStatsExceptions(atomTag, data),
+ BackgroundThread.getExecutor()
+ );
}
- private void pullBinderCallsExceptions() {
- // No op.
+ private int pullBinderCallsStatsExceptions(int atomTag, List<StatsEvent> pulledData) {
+ BinderCallsStatsService.Internal binderStats =
+ LocalServices.getService(BinderCallsStatsService.Internal.class);
+ if (binderStats == null) {
+ Slog.e(TAG, "failed to get binderStats");
+ return StatsManager.PULL_SKIP;
+ }
+
+ ArrayMap<String, Integer> exceptionStats = binderStats.getExportedExceptionStats();
+ // TODO: decouple binder calls exceptions with the rest of the binder calls data so that we
+ // can reset the exception stats.
+ for (Map.Entry<String, Integer> entry : exceptionStats.entrySet()) {
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeString(entry.getKey())
+ .writeInt(entry.getValue())
+ .build();
+ pulledData.add(e);
+ }
+ return StatsManager.PULL_SUCCESS;
}
private void registerLooperStats() {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 3f3408f..b596d2a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1680,6 +1680,7 @@
if (root == this) {
task.setRootProcess(proc);
}
+ proc.addActivityIfNeeded(this);
}
boolean hasProcess() {
@@ -6918,7 +6919,7 @@
// Update last reported values.
final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
- setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
+ setLastReportedConfiguration(getProcessGlobalConfiguration(), newMergedOverrideConfig);
if (mState == INITIALIZING) {
// No need to relaunch or schedule new config for activity that hasn't been launched
@@ -7017,6 +7018,11 @@
return true;
}
+ /** Get process configuration, or global config if the process is not set. */
+ private Configuration getProcessGlobalConfiguration() {
+ return app != null ? app.getConfiguration() : mAtmService.getGlobalConfiguration();
+ }
+
/**
* When assessing a configuration change, decide if the changes flags and the new configurations
* should cause the Activity to relaunch.
@@ -7129,7 +7135,7 @@
startRelaunching();
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
pendingNewIntents, configChangeFlags,
- new MergedConfiguration(mAtmService.getGlobalConfiguration(),
+ new MergedConfiguration(getProcessGlobalConfiguration(),
getMergedOverrideConfiguration()),
preserveWindow);
final ActivityLifecycleItem lifecycleItem;
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index aa90248..0a68408 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -848,8 +848,6 @@
if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
- proc.addActivityIfNeeded(r);
-
final LockTaskController lockTaskController = mService.getLockTaskController();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
|| task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index e308f6b..47e8b87 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -6743,7 +6743,7 @@
return;
}
process.mIsImeProcess = true;
- process.registerDisplayConfigurationListenerLocked(displayContent);
+ process.registerDisplayConfigurationListener(displayContent);
}
}
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 1e60ce8..7b23e2d 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -134,8 +134,8 @@
resolveOverrideConfiguration(newParentConfig);
mFullConfiguration.setTo(newParentConfig);
mFullConfiguration.updateFrom(mResolvedOverrideConfiguration);
+ onMergedOverrideConfigurationChanged();
if (!mResolvedTmpConfig.equals(mResolvedOverrideConfiguration)) {
- onMergedOverrideConfigurationChanged();
// This depends on the assumption that change-listeners don't do
// their own override resolution. This way, dependent hierarchies
// can stay properly synced-up with a primary hierarchy's constraints.
@@ -147,6 +147,10 @@
mResolvedOverrideConfiguration);
}
}
+ for (int i = mChangeListeners.size() - 1; i >= 0; --i) {
+ mChangeListeners.get(i).onMergedOverrideConfigurationChanged(
+ mMergedOverrideConfiguration);
+ }
if (forwardToChildren) {
for (int i = getChildCount() - 1; i >= 0; --i) {
final ConfigurationContainer child = getChildAt(i);
@@ -545,6 +549,7 @@
}
mChangeListeners.add(listener);
listener.onRequestedOverrideConfigurationChanged(mResolvedOverrideConfiguration);
+ listener.onMergedOverrideConfigurationChanged(mMergedOverrideConfiguration);
}
void unregisterConfigurationChangeListener(ConfigurationContainerListener listener) {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainerListener.java b/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
index dc4939d..3d84e17 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainerListener.java
@@ -24,5 +24,8 @@
public interface ConfigurationContainerListener {
/** {@see ConfigurationContainer#onRequestedOverrideConfigurationChanged} */
- void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration);
+ default void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {}
+
+ /** Called when new merged override configuration is reported. */
+ default void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfiguration) {}
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 9a40b1b1..ceb38f7 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.os.Build.VERSION_CODES.Q;
import static android.view.Display.INVALID_DISPLAY;
@@ -178,8 +179,10 @@
// Last configuration that was reported to the process.
private final Configuration mLastReportedConfiguration;
+ private final Configuration mNewOverrideConfig = new Configuration();
// Registered display id as a listener to override config change
private int mDisplayId;
+ private ActivityRecord mConfigActivityRecord;
/** Whether our process is currently running a {@link RecentsAnimation} */
private boolean mRunningRecentsAnimation;
@@ -327,6 +330,12 @@
return mDisplayId != INVALID_DISPLAY;
}
+ /** @return {@code true} if the process registered to an activity as a config listener. */
+ @VisibleForTesting
+ boolean registeredForActivityConfigChanges() {
+ return mConfigActivityRecord != null;
+ }
+
void postPendingUiCleanMsg(boolean pendingUiClean) {
if (mListener == null) return;
// Posting on handler so WM lock isn't held when we call into AM.
@@ -483,7 +492,10 @@
@Override
protected ConfigurationContainer getParent() {
- return null;
+ // Returning RootWindowContainer as the parent, so that this process controller always
+ // has full configuration and overrides (e.g. from display) are always added on top of
+ // global config.
+ return mAtm.mRootWindowContainer;
}
@HotPath(caller = HotPath.PROCESS_CHANGE)
@@ -507,10 +519,12 @@
return;
}
mActivities.add(r);
+ updateActivityConfigurationListener();
}
void removeActivity(ActivityRecord r) {
mActivities.remove(r);
+ updateActivityConfigurationListener();
}
void makeFinishingForProcessRemoved() {
@@ -521,6 +535,7 @@
void clearActivities() {
mActivities.clear();
+ updateActivityConfigurationListener();
}
@HotPath(caller = HotPath.OOM_ADJUSTMENT)
@@ -964,19 +979,20 @@
mAtm.mH.sendMessage(m);
}
- void registerDisplayConfigurationListenerLocked(DisplayContent displayContent) {
+ void registerDisplayConfigurationListener(DisplayContent displayContent) {
if (displayContent == null) {
return;
}
- // A process can only register to one display to listener to the override configuration
+ // A process can only register to one display to listen to the override configuration
// change. Unregister existing listener if it has one before register the new one.
- unregisterDisplayConfigurationListenerLocked();
+ unregisterDisplayConfigurationListener();
+ unregisterActivityConfigurationListener();
mDisplayId = displayContent.mDisplayId;
displayContent.registerConfigurationChangeListener(this);
}
@VisibleForTesting
- void unregisterDisplayConfigurationListenerLocked() {
+ void unregisterDisplayConfigurationListener() {
if (mDisplayId == INVALID_DISPLAY) {
return;
}
@@ -986,6 +1002,48 @@
displayContent.unregisterConfigurationChangeListener(this);
}
mDisplayId = INVALID_DISPLAY;
+ onMergedOverrideConfigurationChanged(Configuration.EMPTY);
+ }
+
+ private void registerActivityConfigurationListener(ActivityRecord activityRecord) {
+ if (activityRecord == null) {
+ return;
+ }
+ // A process can only register to one activityRecord to listen to the override configuration
+ // change. Unregister existing listener if it has one before register the new one.
+ unregisterDisplayConfigurationListener();
+ unregisterActivityConfigurationListener();
+ mConfigActivityRecord = activityRecord;
+ activityRecord.registerConfigurationChangeListener(this);
+ }
+
+ private void unregisterActivityConfigurationListener() {
+ if (mConfigActivityRecord == null) {
+ return;
+ }
+ mConfigActivityRecord.unregisterConfigurationChangeListener(this);
+ mConfigActivityRecord = null;
+ onMergedOverrideConfigurationChanged(Configuration.EMPTY);
+ }
+
+ /**
+ * Check if activity configuration override for the activity process needs an update and perform
+ * if needed. By default we try to override the process configuration to match the top activity
+ * config to increase app compatibility with multi-window and multi-display. The process will
+ * always track the configuration of the non-finishing activity last added to the process.
+ */
+ private void updateActivityConfigurationListener() {
+ for (int i = mActivities.size() - 1; i >= 0; i--) {
+ final ActivityRecord activityRecord = mActivities.get(i);
+ if (!activityRecord.finishing && !activityRecord.containsListener(this)) {
+ // Eligible activity is found, update listener.
+ registerActivityConfigurationListener(activityRecord);
+ return;
+ }
+ }
+
+ // No eligible activities found, let's remove the configuration listener.
+ unregisterActivityConfigurationListener();
}
@Override
@@ -995,8 +1053,11 @@
}
@Override
- public void onRequestedOverrideConfigurationChanged(Configuration newOverrideConfig) {
- super.onRequestedOverrideConfigurationChanged(newOverrideConfig);
+ public void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig) {
+ // Make sure that we don't accidentally override the activity type.
+ mNewOverrideConfig.setTo(mergedOverrideConfig);
+ mNewOverrideConfig.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
+ super.onRequestedOverrideConfigurationChanged(mNewOverrideConfig);
updateConfiguration();
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 36e9273..a4297416 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3402,7 +3402,7 @@
"Reporting new frame to %s: %s", this,
mWindowFrames.mCompatFrame);
final MergedConfiguration mergedConfiguration =
- new MergedConfiguration(mWmService.mRoot.getConfiguration(),
+ new MergedConfiguration(getProcessGlobalConfiguration(),
getMergedOverrideConfiguration());
setLastReportedMergedConfiguration(mergedConfiguration);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3dee913..109a6fd 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -218,7 +218,7 @@
private static final String STATS_COMPANION_LIFECYCLE_CLASS =
"com.android.server.stats.StatsCompanion$Lifecycle";
private static final String STATS_PULL_ATOM_SERVICE_CLASS =
- "com.android.server.stats.StatsPullAtomService";
+ "com.android.server.stats.pull.StatsPullAtomService";
private static final String USB_SERVICE_CLASS =
"com.android.server.usb.UsbService$Lifecycle";
private static final String MIDI_SERVICE_CLASS =
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java
new file mode 100644
index 0000000..09466e7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+
+import static org.mockito.Mockito.verify;
+
+import android.os.RemoteException;
+import android.view.Display;
+import android.view.accessibility.IWindowMagnificationConnection;
+import android.view.accessibility.IWindowMagnificationConnectionCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for WindowMagnificationConnectionWrapper. We don't test {@code
+ * WindowMagnificationConnectionWrapper#linkToDeath(IBinder.DeathRecipient)} since it's tested in
+ * {@link WindowMagnificationManagerTest}.
+ */
+public class WindowMagnificationConnectionWrapperTest {
+
+ private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY;
+
+ @Mock
+ private IWindowMagnificationConnection mConnection;
+ @Mock
+ private IWindowMagnificationConnectionCallback mCallback;
+ private WindowMagnificationConnectionWrapper mConnectionWrapper;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mConnectionWrapper = new WindowMagnificationConnectionWrapper(mConnection);
+ }
+
+ @Test
+ public void enableWindowMagnification() throws RemoteException {
+ mConnectionWrapper.enableWindowMagnification(TEST_DISPLAY, 2, 100f, 200f);
+ verify(mConnection).enableWindowMagnification(TEST_DISPLAY, 2, 100f, 200f);
+ }
+
+ @Test
+ public void setScale() throws RemoteException {
+ mConnectionWrapper.setScale(TEST_DISPLAY, 3.0f);
+ verify(mConnection).setScale(TEST_DISPLAY, 3.0f);
+ }
+
+ @Test
+ public void disableWindowMagnification() throws RemoteException {
+ mConnectionWrapper.disableWindowMagnification(TEST_DISPLAY);
+ verify(mConnection).disableWindowMagnification(TEST_DISPLAY);
+ }
+
+ @Test
+ public void moveWindowMagnifier() throws RemoteException {
+ mConnectionWrapper.moveWindowMagnifier(0, 100, 150);
+ verify(mConnection).moveWindowMagnifier(0, 100, 150);
+ }
+
+ @Test
+ public void setMirrorWindowCallback() throws RemoteException {
+ mConnectionWrapper.setConnectionCallback(mCallback);
+ verify(mConnection).setConnectionCallback(mCallback);
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
new file mode 100644
index 0000000..780a6c0
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+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 static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.accessibility.IWindowMagnificationConnection;
+import android.view.accessibility.IWindowMagnificationConnectionCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for WindowMagnificationManager.
+ */
+public class WindowMagnificationManagerTest {
+
+ private MockWindowMagnificationConnection mMockConnection;
+ private WindowMagnificationManager mWindowMagnificationManager;
+
+ @Before
+ public void setUp() {
+ mMockConnection = new MockWindowMagnificationConnection();
+ mWindowMagnificationManager = new WindowMagnificationManager();
+ }
+
+ @Test
+ public void setConnection_connectionIsNull_wrapperIsNullAndLinkToDeath() {
+ mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
+ assertNotNull(mWindowMagnificationManager.mConnectionWrapper);
+ verify(mMockConnection.asBinder()).linkToDeath(any(IBinder.DeathRecipient.class), eq(0));
+ }
+
+ @Test
+ public void setConnection_connectionIsNull_setMirrorWindowCallbackAndHasWrapper()
+ throws RemoteException {
+ mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
+
+ assertNotNull(mWindowMagnificationManager.mConnectionWrapper);
+ verify(mMockConnection.asBinder()).linkToDeath(any(IBinder.DeathRecipient.class), eq(0));
+ verify(mMockConnection.getConnection()).setConnectionCallback(
+ any(IWindowMagnificationConnectionCallback.class));
+ }
+
+ @Test
+ public void binderDied_hasConnection_wrapperIsNullAndUnlinkToDeath() {
+ mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
+
+ mMockConnection.getDeathRecipient().binderDied();
+
+ assertNull(mWindowMagnificationManager.mConnectionWrapper);
+ verify(mMockConnection.asBinder()).unlinkToDeath(mMockConnection.getDeathRecipient(),
+ 0);
+ }
+
+ /**
+ * This test simulates {@link WindowMagnificationManager#setConnection} is called by thread A
+ * and then the former connection is called by thread B. In this situation we should keep the
+ * new connection.
+ */
+ @Test
+ public void
+ setSecondConnectionAndFormerConnectionBinderDead_hasWrapperAndNotCallUnlinkToDeath() {
+ mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
+ MockWindowMagnificationConnection secondConnection =
+ new MockWindowMagnificationConnection();
+
+ mWindowMagnificationManager.setConnection(secondConnection.getConnection());
+ mMockConnection.getDeathRecipient().binderDied();
+
+ assertNotNull(mWindowMagnificationManager.mConnectionWrapper);
+ verify(mMockConnection.asBinder()).unlinkToDeath(mMockConnection.getDeathRecipient(), 0);
+ verify(secondConnection.asBinder(), never()).unlinkToDeath(
+ secondConnection.getDeathRecipient(), 0);
+ }
+
+ @Test
+ public void setNullConnection_hasConnection_wrapperIsNull() throws RemoteException {
+ mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
+
+ mWindowMagnificationManager.setConnection(null);
+
+ assertNull(mWindowMagnificationManager.mConnectionWrapper);
+ verify(mMockConnection.getConnection()).setConnectionCallback(null);
+ }
+
+ private static class MockWindowMagnificationConnection {
+
+ private final IWindowMagnificationConnection mConnection;
+ private final Binder mBinder;
+ private IBinder.DeathRecipient mDeathRecipient;
+
+ MockWindowMagnificationConnection() {
+ mConnection = mock(IWindowMagnificationConnection.class);
+ mBinder = mock(Binder.class);
+ when(mConnection.asBinder()).thenReturn(mBinder);
+ doAnswer((invocation) -> {
+ mDeathRecipient = invocation.getArgument(0);
+ return null;
+ }).when(mBinder).linkToDeath(
+ any(IBinder.DeathRecipient.class), eq(0));
+ }
+
+ IWindowMagnificationConnection getConnection() {
+ return mConnection;
+ }
+
+ public IBinder.DeathRecipient getDeathRecipient() {
+ return mDeathRecipient;
+ }
+
+ Binder asBinder() {
+ return mBinder;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/stats/IonMemoryUtilTest.java b/services/tests/servicestests/src/com/android/server/stats/pull/IonMemoryUtilTest.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/stats/IonMemoryUtilTest.java
rename to services/tests/servicestests/src/com/android/server/stats/pull/IonMemoryUtilTest.java
index 8cbf8e5..d4d4b4d 100644
--- a/services/tests/servicestests/src/com/android/server/stats/IonMemoryUtilTest.java
+++ b/services/tests/servicestests/src/com/android/server/stats/pull/IonMemoryUtilTest.java
@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.stats;
+package com.android.server.stats.pull;
-import static com.android.server.stats.IonMemoryUtil.parseIonHeapSizeFromDebugfs;
-import static com.android.server.stats.IonMemoryUtil.parseProcessIonHeapSizesFromDebugfs;
+import static com.android.server.stats.pull.IonMemoryUtil.parseIonHeapSizeFromDebugfs;
+import static com.android.server.stats.pull.IonMemoryUtil.parseProcessIonHeapSizesFromDebugfs;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.filters.SmallTest;
-import com.android.server.stats.IonMemoryUtil.IonAllocations;
+import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
import org.junit.Test;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index a3e94599..ad63d07 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
@@ -56,6 +58,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -1175,4 +1178,160 @@
verify(mActivity).removeFromHistory(anyString());
}
+
+ @Test
+ public void testActivityOverridesProcessConfig() {
+ final WindowProcessController wpc = mActivity.app;
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertFalse(wpc.registeredForDisplayConfigChanges());
+
+ final ActivityRecord secondaryDisplayActivity =
+ createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
+
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertEquals(0, mActivity.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ assertNotEquals(mActivity.getConfiguration(),
+ secondaryDisplayActivity.getConfiguration());
+ }
+
+ @Test
+ public void testActivityOverridesProcessConfig_TwoActivities() {
+ final WindowProcessController wpc = mActivity.app;
+ assertTrue(wpc.registeredForActivityConfigChanges());
+
+ final Task firstTaskRecord = mActivity.getTask();
+ final ActivityRecord secondActivityRecord =
+ new ActivityBuilder(mService).setTask(firstTaskRecord).setUseProcess(wpc).build();
+
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ }
+
+ @Test
+ public void testActivityOverridesProcessConfig_TwoActivities_SecondaryDisplay() {
+ final WindowProcessController wpc = mActivity.app;
+ assertTrue(wpc.registeredForActivityConfigChanges());
+
+ final ActivityRecord secondActivityRecord =
+ new ActivityBuilder(mService).setTask(mTask).setUseProcess(wpc).build();
+
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ }
+
+ @Test
+ public void testActivityOverridesProcessConfig_TwoActivities_DifferentTasks() {
+ final WindowProcessController wpc = mActivity.app;
+ assertTrue(wpc.registeredForActivityConfigChanges());
+
+ final ActivityRecord secondActivityRecord =
+ createActivityOnDisplay(true /* defaultDisplay */, wpc);
+
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ }
+
+ @Test
+ public void testActivityOnDifferentDisplayUpdatesProcessOverride() {
+ final ActivityRecord secondaryDisplayActivity =
+ createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
+ final WindowProcessController wpc = secondaryDisplayActivity.app;
+ assertTrue(wpc.registeredForActivityConfigChanges());
+
+ final ActivityRecord secondActivityRecord =
+ createActivityOnDisplay(true /* defaultDisplay */, wpc);
+
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ assertFalse(wpc.registeredForDisplayConfigChanges());
+ }
+
+ @Test
+ public void testActivityReparentChangesProcessOverride() {
+ final WindowProcessController wpc = mActivity.app;
+ final Task initialTask = mActivity.getTask();
+ final Configuration initialConf =
+ new Configuration(mActivity.getMergedOverrideConfiguration());
+ assertEquals(0, mActivity.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ assertTrue(wpc.registeredForActivityConfigChanges());
+
+ // Create a new task with custom config to reparent the activity to.
+ final Task newTask =
+ new TaskBuilder(mSupervisor).setStack(initialTask.getStack()).build();
+ final Configuration newConfig = newTask.getConfiguration();
+ newConfig.densityDpi += 100;
+ newTask.onRequestedOverrideConfigurationChanged(newConfig);
+ assertEquals(newTask.getConfiguration().densityDpi, newConfig.densityDpi);
+
+ // Reparent the activity and verify that config override changed.
+ mActivity.reparent(newTask, 0 /* top */, "test");
+ assertEquals(mActivity.getConfiguration().densityDpi, newConfig.densityDpi);
+ assertEquals(mActivity.getMergedOverrideConfiguration().densityDpi, newConfig.densityDpi);
+
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertNotEquals(initialConf, wpc.getRequestedOverrideConfiguration());
+ assertEquals(0, mActivity.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ }
+
+ @Test
+ public void testActivityReparentDoesntClearProcessOverride_TwoActivities() {
+ final WindowProcessController wpc = mActivity.app;
+ final Configuration initialConf =
+ new Configuration(mActivity.getMergedOverrideConfiguration());
+ final Task initialTask = mActivity.getTask();
+ final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(initialTask)
+ .setUseProcess(wpc).build();
+
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertEquals(0, secondActivity.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+
+ // Create a new task with custom config to reparent the second activity to.
+ final Task newTask =
+ new TaskBuilder(mSupervisor).setStack(initialTask.getStack()).build();
+ final Configuration newConfig = newTask.getConfiguration();
+ newConfig.densityDpi += 100;
+ newTask.onRequestedOverrideConfigurationChanged(newConfig);
+
+ // Reparent the activity and verify that config override changed.
+ secondActivity.reparent(newTask, 0 /* top */, "test");
+
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertEquals(0, secondActivity.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ assertNotEquals(initialConf, wpc.getRequestedOverrideConfiguration());
+
+ // Reparent the first activity and verify that config override didn't change.
+ mActivity.reparent(newTask, 1 /* top */, "test");
+ assertTrue(wpc.registeredForActivityConfigChanges());
+ assertEquals(0, secondActivity.getMergedOverrideConfiguration()
+ .diff(wpc.getRequestedOverrideConfiguration()));
+ assertNotEquals(initialConf, wpc.getRequestedOverrideConfiguration());
+ }
+
+ /**
+ * Creates an activity on display. For non-default display request it will also create a new
+ * display with custom DisplayInfo.
+ */
+ private ActivityRecord createActivityOnDisplay(boolean defaultDisplay,
+ WindowProcessController process) {
+ final DisplayContent display;
+ if (defaultDisplay) {
+ display = mRootWindowContainer.getDefaultDisplay();
+ } else {
+ display = new TestDisplayContent.Builder(mService, 2000, 1000).setDensityDpi(300)
+ .setPosition(DisplayContent.POSITION_TOP).build();
+ }
+ final ActivityStack stack = display.createStack(WINDOWING_MODE_UNDEFINED,
+ ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
+ return new ActivityBuilder(mService).setTask(task).setUseProcess(process).build();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 0f22724..4beede9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -111,6 +111,7 @@
private int mConfigChanges;
private int mLaunchedFromPid;
private int mLaunchedFromUid;
+ private WindowProcessController mWpc;
ActivityBuilder(ActivityTaskManagerService service) {
mService = service;
@@ -201,6 +202,11 @@
return this;
}
+ ActivityBuilder setUseProcess(WindowProcessController wpc) {
+ mWpc = wpc;
+ return this;
+ }
+
ActivityRecord build() {
try {
mService.deferWindowLayout();
@@ -263,10 +269,16 @@
activity.setVisible(true);
}
- final WindowProcessController wpc = new WindowProcessController(mService,
- mService.mContext.getApplicationInfo(), mProcessName, mUid,
- UserHandle.getUserId(12345), mock(Object.class),
- mock(WindowProcessListener.class));
+ final WindowProcessController wpc;
+ if (mWpc != null) {
+ wpc = mWpc;
+ } else {
+ wpc = new WindowProcessController(mService,
+ mService.mContext.getApplicationInfo(), mProcessName, mUid,
+ UserHandle.getUserId(12345), mock(Object.class),
+ mock(WindowProcessListener.class));
+ wpc.setThread(mock(IApplicationThread.class));
+ }
wpc.setThread(mock(IApplicationThread.class));
activity.setProcess(wpc);
doReturn(wpc).when(mService).getProcessController(
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 421a4582..db4fdc77 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.times;
import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
import android.platform.test.annotations.Presubmit;
import org.junit.Before;
@@ -62,33 +63,33 @@
// Register to display 1 as a listener.
TestDisplayContent testDisplayContent1 = createTestDisplayContentInContainer();
- mWpc.registerDisplayConfigurationListenerLocked(testDisplayContent1);
+ mWpc.registerDisplayConfigurationListener(testDisplayContent1);
assertTrue(testDisplayContent1.containsListener(mWpc));
assertEquals(testDisplayContent1.mDisplayId, mWpc.getDisplayId());
// Move to display 2.
TestDisplayContent testDisplayContent2 = createTestDisplayContentInContainer();
- mWpc.registerDisplayConfigurationListenerLocked(testDisplayContent2);
+ mWpc.registerDisplayConfigurationListener(testDisplayContent2);
assertFalse(testDisplayContent1.containsListener(mWpc));
assertTrue(testDisplayContent2.containsListener(mWpc));
assertEquals(testDisplayContent2.mDisplayId, mWpc.getDisplayId());
// Null DisplayContent will not change anything.
- mWpc.registerDisplayConfigurationListenerLocked(null);
+ mWpc.registerDisplayConfigurationListener(null);
assertTrue(testDisplayContent2.containsListener(mWpc));
assertEquals(testDisplayContent2.mDisplayId, mWpc.getDisplayId());
// Unregister listener will remove the wpc from registered displays.
- mWpc.unregisterDisplayConfigurationListenerLocked();
+ mWpc.unregisterDisplayConfigurationListener();
assertFalse(testDisplayContent1.containsListener(mWpc));
assertFalse(testDisplayContent2.containsListener(mWpc));
assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
// Unregistration still work even if the display was removed.
- mWpc.registerDisplayConfigurationListenerLocked(testDisplayContent1);
+ mWpc.registerDisplayConfigurationListener(testDisplayContent1);
assertEquals(testDisplayContent1.mDisplayId, mWpc.getDisplayId());
mRootWindowContainer.removeChild(testDisplayContent1);
- mWpc.unregisterDisplayConfigurationListenerLocked();
+ mWpc.unregisterDisplayConfigurationListener();
assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
}
@@ -129,6 +130,24 @@
orderVerifier.verifyNoMoreInteractions();
}
+ @Test
+ public void testConfigurationForSecondaryScreen() {
+ final WindowProcessController wpc = new WindowProcessController(
+ mService, mock(ApplicationInfo.class), null, 0, -1, null, null);
+ // By default, the process should not listen to any display.
+ assertEquals(INVALID_DISPLAY, wpc.getDisplayId());
+
+ // Register to a new display as a listener.
+ final DisplayContent display = new TestDisplayContent.Builder(mService, 2000, 1000)
+ .setDensityDpi(300).setPosition(DisplayContent.POSITION_TOP).build();
+ wpc.registerDisplayConfigurationListener(display);
+
+ assertEquals(display.mDisplayId, wpc.getDisplayId());
+ final Configuration expectedConfig = mService.mRootWindowContainer.getConfiguration();
+ expectedConfig.updateFrom(display.getConfiguration());
+ assertEquals(expectedConfig, wpc.getConfiguration());
+ }
+
private TestDisplayContent createTestDisplayContentInContainer() {
return new TestDisplayContent.Builder(mService, 1000, 1500).build();
}
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 9b739d3..8c11df4 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -27,6 +27,7 @@
import android.annotation.WorkerThread;
import android.os.Binder;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
@@ -383,6 +384,8 @@
callback.setExecutor(executor);
try {
getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder());
+ } catch (ServiceSpecificException e) {
+ throw new ImsException(e.getMessage(), e.errorCode);
} catch (RemoteException | IllegalStateException e) {
throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 11d5b25..1c69209 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
@@ -74,6 +75,7 @@
final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
mNetworkCapabilities.addTransportType(transport);
switch (transport) {
case TRANSPORT_ETHERNET:
@@ -206,13 +208,11 @@
}
public void suspend() {
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
}
public void resume() {
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ addCapability(NET_CAPABILITY_NOT_SUSPENDED);
}
public void disconnect() {
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index 8f72040..d377ee6 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -1,5 +1,7 @@
rule android.net.InterfaceConfigurationParcel* @0
rule android.net.InterfaceConfiguration* com.android.server.x.wifi.net.InterfaceConfiguration@1
+rule android.net.NetworkFactory* com.android.server.x.wifi.net.NetworkFactory@1
+rule android.net.util.NetUtils* com.android.server.x.wifi.net.util.NetUtils@1
# We don't jar-jar the entire package because, we still use some classes (like
# AsyncChannel in com.android.internal.util) from these packages which are not
@@ -32,6 +34,7 @@
rule android.content.pm.BaseParceledListSlice* android.x.net.wifi.util.BaseParceledListSlice@1
rule android.content.pm.ParceledListSlice* android.x.net.wifi.util.ParceledListSlice@1
rule android.net.shared.Inet4AddressUtils* android.x.net.wifi.util.Inet4AddressUtils@1
+rule android.net.util.MacAddressUtils* android.x.net.wifi.util.MacAddressUtils@1
rule android.os.HandlerExecutor* android.x.net.wifi.util.HandlerExecutor@1
rule android.telephony.Annotation* android.x.net.wifi.util.TelephonyAnnotation@1
rule com.android.internal.util.AsyncChannel* android.x.net.wifi.util.AsyncChannel@1