Merge "[SettingsProvider] lint checks for non-user getter calls from system server"
diff --git a/Android.bp b/Android.bp
index 62dce7f..3afd6ec 100644
--- a/Android.bp
+++ b/Android.bp
@@ -101,6 +101,7 @@
// AIDL sources from external directories
":android.hardware.security.keymint-V1-java-source",
":android.hardware.security.secureclock-V1-java-source",
+ ":android.hardware.tv.tuner-V1-java-source",
":android.security.apc-java-source",
":android.security.authorization-java-source",
":android.security.legacykeystore-java-source",
@@ -250,8 +251,6 @@
"android.hardware.thermal-V1.1-java",
"android.hardware.thermal-V2.0-java",
"android.hardware.tv.input-V1.0-java-constants",
- "android.hardware.tv.tuner-V1.0-java-constants",
- "android.hardware.tv.tuner-V1.1-java-constants",
"android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants",
"android.hardware.usb-V1.2-java-constants",
@@ -331,6 +330,7 @@
],
sdk_version: "core_platform",
static_libs: [
+ "android.hardware.common.fmq-V1-java",
// TODO(b/184162091)
"android.hardware.soundtrigger3-V1-java",
"bouncycastle-repackaged-unbundled",
@@ -559,8 +559,6 @@
"android.hardware.thermal-V1.0-java-constants",
"android.hardware.thermal-V2.0-java",
"android.hardware.tv.input-V1.0-java-constants",
- "android.hardware.tv.tuner-V1.0-java-constants",
- "android.hardware.tv.tuner-V1.1-java-constants",
"android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants",
"android.hardware.usb.gadget-V1.0-java",
diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp
index 0e76488..fc70219 100644
--- a/apct-tests/perftests/packagemanager/Android.bp
+++ b/apct-tests/perftests/packagemanager/Android.bp
@@ -20,6 +20,7 @@
"androidx.annotation_annotation",
"apct-perftests-utils",
"collector-device-lib-platform",
+ "cts-install-lib-java",
],
libs: ["android.test.base"],
diff --git a/apct-tests/perftests/packagemanager/AndroidManifest.xml b/apct-tests/perftests/packagemanager/AndroidManifest.xml
index 4bcd557..3b9431f 100644
--- a/apct-tests/perftests/packagemanager/AndroidManifest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidManifest.xml
@@ -17,6 +17,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.perftests.packagemanager">
+ <!-- prevent test application from being obscured because of package visibility -->
+ <queries>
+ <package android:name="com.android.cts.install.lib.testapp.A" />
+ <package android:name="com.android.cts.install.lib.testapp.B" />
+ <package android:name="com.android.cts.install.lib.testapp.C" />
+ </queries>
<permission android:name="com.android.perftests.packagemanager.TestPermission" />
<uses-permission android:name="com.android.perftests.packagemanager.TestPermission" />
diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml
index 4903510..c9d45a6 100644
--- a/apct-tests/perftests/packagemanager/AndroidTest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidTest.xml
@@ -130,6 +130,10 @@
<option name="instrumentation-arg" key="perfetto_config_file"
value="trace_config.textproto"/>
+ <!--
+ PackageInstallerBenchmark will break for 5 minutes time out so it changes to 10 minutes
+ -->
+ <option name="test-timeout" value="600000" />
</test>
diff --git a/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java b/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java
new file mode 100644
index 0000000..3b4f72b
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2021 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.content.pm;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.HandlerThread;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.cts.install.lib.Install;
+import com.android.cts.install.lib.InstallUtils;
+import com.android.cts.install.lib.LocalIntentSender;
+import com.android.cts.install.lib.TestApp;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class PackageInstallerBenchmark {
+ private static final String TAG = "PackageInstallerBenchmark";
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ /**
+ * This rule adopts the Shell process permissions, needed because INSTALL_PACKAGES
+ * and DELETE_PACKAGES are privileged permission.
+ */
+ @Rule
+ public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES);
+
+ private static class SessionCallback extends PackageInstaller.SessionCallback {
+ private final List<Integer> mExpectedSessions;
+ private final CountDownLatch mCountDownLatch;
+ private final boolean mExpectedSuccess;
+
+ SessionCallback(boolean expectedSuccess, List<Integer> expectedSessions,
+ @NonNull CountDownLatch countDownLatch) {
+ mExpectedSuccess = expectedSuccess;
+ mCountDownLatch = countDownLatch;
+ mExpectedSessions = expectedSessions;
+ }
+
+ @Override
+ public void onCreated(int sessionId) { }
+
+ @Override
+ public void onBadgingChanged(int sessionId) { }
+
+ @Override
+ public void onActiveChanged(int sessionId, boolean active) { }
+
+ @Override
+ public void onProgressChanged(int sessionId, float progress) { }
+
+ @Override
+ public void onFinished(int sessionId, boolean success) {
+ if (success == mExpectedSuccess && mExpectedSessions.contains(sessionId)) {
+ mCountDownLatch.countDown();
+ }
+ }
+ }
+
+ private CountDownLatch mCountDownLatch;
+ private SessionCallback mSessionCallback;
+ private PackageInstaller mPackageInstaller;
+ private Install mInstall;
+ private HandlerThread mHandlerThread;
+ private List<PackageInstaller.Session> mExpectedSessions;
+ private List<Integer> mExpectedSessionIds;
+ final LocalIntentSender mLocalIntentSender = new LocalIntentSender();
+ private IntentSender mIntentSender;
+
+ @Before
+ public void setUp() throws IOException {
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mPackageInstaller = context.getPackageManager().getPackageInstaller();
+ mHandlerThread = new HandlerThread("PackageInstallerBenchmark");
+ mHandlerThread.start();
+
+ mIntentSender = mLocalIntentSender.getIntentSender();
+ }
+
+ @After
+ public void tearDown() throws InterruptedException {
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ context.unregisterReceiver(mLocalIntentSender);
+
+ uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+ mHandlerThread.quitSafely();
+ }
+
+ private List<PackageInstaller.Session> createSinglePackageSessions(
+ BenchmarkState state, boolean expectedResult, TestApp...testApps)
+ throws IOException, InterruptedException {
+ state.pauseTiming();
+ uninstall(false /* stop at fail */, testApps);
+
+ mExpectedSessions = new ArrayList<>();
+ mExpectedSessionIds = new ArrayList<>();
+ for (TestApp testApp : testApps) {
+ mInstall = Install.single(testApp);
+ final int expectedSessionId = mInstall.createSession();
+ PackageInstaller.Session session =
+ InstallUtils.openPackageInstallerSession(expectedSessionId);
+ Log.d(TAG, "createNewSession: session expectedSessionId = " + expectedSessionId);
+ mExpectedSessions.add(session);
+ mExpectedSessionIds.add(expectedSessionId);
+ }
+
+ mCountDownLatch = new CountDownLatch(mExpectedSessions.size());
+ mSessionCallback = new SessionCallback(expectedResult, mExpectedSessionIds,
+ mCountDownLatch);
+ mPackageInstaller.registerSessionCallback(mSessionCallback,
+ mHandlerThread.getThreadHandler());
+ state.resumeTiming();
+ return mExpectedSessions;
+ }
+
+ private List<PackageInstaller.Session> createMultiplePackageSessions(BenchmarkState state,
+ boolean expectedSuccess, List<TestApp[]> testAppsList)
+ throws IOException, InterruptedException {
+ state.pauseTiming();
+ mExpectedSessions = new ArrayList<>();
+ mExpectedSessionIds = new ArrayList<>();
+ for (TestApp[] testApps : testAppsList) {
+ uninstall(false /* stop at fail */, testApps);
+
+ mInstall = Install.multi(testApps);
+ final int expectedSessionId = mInstall.createSession();
+ PackageInstaller.Session session =
+ InstallUtils.openPackageInstallerSession(expectedSessionId);
+ mExpectedSessions.add(session);
+ mExpectedSessionIds.add(expectedSessionId);
+ }
+
+ mCountDownLatch = new CountDownLatch(mExpectedSessions.size());
+ mSessionCallback = new SessionCallback(expectedSuccess, mExpectedSessionIds,
+ mCountDownLatch);
+ mPackageInstaller.registerSessionCallback(mSessionCallback,
+ mHandlerThread.getThreadHandler());
+ state.resumeTiming();
+ return mExpectedSessions;
+ }
+
+ private void uninstall(boolean stopAtFail, TestApp...testApps) throws InterruptedException {
+ String[] packageNames = new String[testApps.length];
+ for (int i = 0; i < testApps.length; i++) {
+ packageNames[i] = testApps[i].getPackageName();
+ }
+ uninstall(stopAtFail, packageNames);
+ }
+
+ private void uninstall(boolean stopAtFail, String...packageNames) throws InterruptedException {
+ LocalIntentSender localIntentSender = new LocalIntentSender();
+ IntentSender intentSender = localIntentSender.getIntentSender();
+ for (String packageName : packageNames) {
+ try {
+ mPackageInstaller.uninstall(packageName, intentSender);
+ } catch (IllegalArgumentException e) {
+ continue;
+ }
+ Intent intent = localIntentSender.getResult();
+ if (stopAtFail) {
+ InstallUtils.assertStatusSuccess(intent);
+ }
+ }
+
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ context.unregisterReceiver(localIntentSender);
+ }
+
+ private void uninstallSession(BenchmarkState state, String...packageNames)
+ throws InterruptedException {
+ state.pauseTiming();
+ uninstall(true /* stop at fail */, packageNames);
+ mPackageInstaller.unregisterSessionCallback(mSessionCallback);
+ state.resumeTiming();
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_aSingleApkSession_untilFinishBenchmark() throws Exception {
+ uninstall(false /* stop at fail */, TestApp.A);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions =
+ createSinglePackageSessions(state, true, TestApp.A1);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A);
+ }
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_threeSingleApkSessions_untilFinishBenchmark() throws Exception {
+ uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions = createSinglePackageSessions(
+ state, true, TestApp.A1, TestApp.B1, TestApp.C1);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+ }
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_aMultiplePackagesSession_untilFinishBenchmark()
+ throws IOException, InterruptedException {
+ uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final List<TestApp[]> multiPackageApps = new ArrayList<>();
+ multiPackageApps.add(new TestApp[] {TestApp.A1, TestApp.B1, TestApp.C1});
+
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions = createMultiplePackageSessions(
+ state, true, multiPackageApps);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+ }
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_threeMultiplePackageSessions_untilFinishBenchmark()
+ throws Exception {
+ uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final List<TestApp[]> multiPackageApps = new ArrayList<>();
+ multiPackageApps.add(new TestApp[] {TestApp.A1});
+ multiPackageApps.add(new TestApp[] {TestApp.B1});
+ multiPackageApps.add(new TestApp[] {TestApp.C1});
+
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions = createMultiplePackageSessions(
+ state, true, multiPackageApps);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+ }
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_aMultipleApksSession_untilFinishBenchmark()
+ throws IOException, InterruptedException {
+ uninstall(false /* stop at fail */, TestApp.A);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions = createSinglePackageSessions(
+ state, true, TestApp.ASplit1);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A);
+ }
+ }
+}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
index 6e4a5a0..7b287d5 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
@@ -19,6 +19,7 @@
import android.annotation.SystemApi;
import android.app.JobSchedulerImpl;
import android.app.SystemServiceRegistry;
+import android.app.tare.EconomyManager;
import android.content.Context;
import android.os.DeviceIdleManager;
import android.os.IDeviceIdleController;
@@ -56,5 +57,7 @@
SystemServiceRegistry.registerContextAwareService(
Context.POWER_EXEMPTION_SERVICE, PowerExemptionManager.class,
PowerExemptionManager::new);
+ SystemServiceRegistry.registerStaticService(
+ Context.RESOURCE_ECONOMY_SERVICE, EconomyManager.class, EconomyManager::new);
}
}
diff --git a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
new file mode 100644
index 0000000..2f3b36c
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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.tare;
+
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * Provides access to the resource economy service.
+ *
+ * @hide
+ */
+@SystemService(Context.RESOURCE_ECONOMY_SERVICE)
+public class EconomyManager {
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index 74ed334..829ad27 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -26,6 +26,8 @@
import static com.android.server.tare.EconomicPolicy.TYPE_REWARD;
import static com.android.server.tare.EconomicPolicy.eventToString;
import static com.android.server.tare.EconomicPolicy.getEventType;
+import static com.android.server.tare.TareUtils.appToString;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
import static com.android.server.tare.TareUtils.narcToString;
import android.annotation.NonNull;
@@ -183,7 +185,7 @@
mCurrentOngoingEvents.get(userId, pkgName);
if (ongoingEvents != null) {
final long nowElapsed = SystemClock.elapsedRealtime();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
mTotalDeltaCalculator.reset(ledger, nowElapsed, now);
ongoingEvents.forEach(mTotalDeltaCalculator);
balance += mTotalDeltaCalculator.mTotal;
@@ -194,7 +196,12 @@
@GuardedBy("mLock")
void noteInstantaneousEventLocked(final int userId, @NonNull final String pkgName,
final int eventId, @Nullable String tag) {
- final long now = System.currentTimeMillis();
+ if (mIrs.isSystem(userId, pkgName)) {
+ // Events are free for the system. Don't bother recording them.
+ return;
+ }
+
+ final long now = getCurrentTimeMillis();
final Ledger ledger = getLedgerLocked(userId, pkgName);
final int eventType = getEventType(eventId);
@@ -278,7 +285,7 @@
@GuardedBy("mLock")
void onDeviceStateChangedLocked() {
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
mCurrentOngoingEvents.forEach((userId, pkgName, ongoingEvents) -> {
@@ -326,7 +333,7 @@
@GuardedBy("mLock")
void onAppStatesChangedLocked(final int userId, @NonNull ArraySet<String> pkgNames) {
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
for (int i = 0; i < pkgNames.size(); ++i) {
@@ -415,12 +422,15 @@
}
ongoingEvent.refCount--;
if (ongoingEvent.refCount <= 0) {
- final long startElapsed = ongoingEvent.startTimeElapsed;
- final long startTime = now - (nowElapsed - startElapsed);
- final long actualDelta = getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now);
- recordTransactionLocked(userId, pkgName, ledger,
- new Ledger.Transaction(startTime, now, eventId, tag, actualDelta),
- notifyOnAffordabilityChange);
+ if (!mIrs.isSystem(userId, pkgName)) {
+ final long startElapsed = ongoingEvent.startTimeElapsed;
+ final long startTime = now - (nowElapsed - startElapsed);
+ final long actualDelta =
+ getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now);
+ recordTransactionLocked(userId, pkgName, ledger,
+ new Ledger.Transaction(startTime, now, eventId, tag, actualDelta),
+ notifyOnAffordabilityChange);
+ }
ongoingEvents.delete(eventId, tag);
}
if (updateBalanceCheck) {
@@ -446,6 +456,15 @@
private void recordTransactionLocked(final int userId, @NonNull final String pkgName,
@NonNull Ledger ledger, @NonNull Ledger.Transaction transaction,
final boolean notifyOnAffordabilityChange) {
+ if (transaction.delta == 0) {
+ // Skip recording transactions with a delta of 0 to save on space.
+ return;
+ }
+ if (mIrs.isSystem(userId, pkgName)) {
+ Slog.wtfStack(TAG,
+ "Tried to adjust system balance for " + appToString(userId, pkgName));
+ return;
+ }
final long maxCirculationAllowed = mIrs.getMaxCirculationLocked();
final long newArcsInCirculation = mCurrentNarcsInCirculation + transaction.delta;
if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) {
@@ -477,7 +496,7 @@
// The earliest transaction won't change until we clean up the ledger, so no point
// continuing to reschedule an existing cleanup.
final long cleanupAlarmElapsed = SystemClock.elapsedRealtime() + MAX_TRANSACTION_AGE_MS
- - (System.currentTimeMillis() - ledger.getEarliestTransaction().endTimeMs);
+ - (getCurrentTimeMillis() - ledger.getEarliestTransaction().endTimeMs);
mLedgerCleanupAlarmListener.addAlarmLocked(userId, pkgName, cleanupAlarmElapsed);
}
// TODO: save changes to disk in a background thread
@@ -509,7 +528,7 @@
@GuardedBy("mLock")
void reclaimUnusedAssetsLocked(double percentage) {
final List<PackageInfo> pkgs = mIrs.getInstalledPackages();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
for (int i = 0; i < pkgs.size(); ++i) {
final int userId = UserHandle.getUserId(pkgs.get(i).applicationInfo.uid);
final String pkgName = pkgs.get(i).packageName;
@@ -543,11 +562,15 @@
@GuardedBy("mLock")
void distributeBasicIncomeLocked(int batteryLevel) {
List<PackageInfo> pkgs = mIrs.getInstalledPackages();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
for (int i = 0; i < pkgs.size(); ++i) {
final PackageInfo pkgInfo = pkgs.get(i);
final int userId = UserHandle.getUserId(pkgInfo.applicationInfo.uid);
final String pkgName = pkgInfo.packageName;
+ if (mIrs.isSystem(userId, pkgName)) {
+ // No point allocating ARCs to the system. It can do whatever it wants.
+ continue;
+ }
Ledger ledger = getLedgerLocked(userId, pkgName);
final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
final double perc = batteryLevel / 100d;
@@ -578,12 +601,16 @@
List<PackageInfo> pkgs = packageManager.getInstalledPackagesAsUser(0, userId);
final long maxBirthright =
mIrs.getMaxCirculationLocked() / mIrs.getInstalledPackages().size();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
for (int i = 0; i < pkgs.size(); ++i) {
final PackageInfo packageInfo = pkgs.get(i);
final String pkgName = packageInfo.packageName;
final Ledger ledger = getLedgerLocked(userId, pkgName);
+ if (mIrs.isSystem(userId, pkgName)) {
+ // No point allocating ARCs to the system. It can do whatever it wants.
+ continue;
+ }
if (ledger.getCurrentBalance() > 0) {
// App already got credits somehow. Move along.
Slog.wtf(TAG, "App " + pkgName + " had credits before economy was set up");
@@ -609,7 +636,7 @@
List<PackageInfo> pkgs = mIrs.getInstalledPackages();
final int numPackages = pkgs.size();
final long maxBirthright = mIrs.getMaxCirculationLocked() / numPackages;
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
recordTransactionLocked(userId, pkgName, ledger,
new Ledger.Transaction(now, now, REGULATION_BIRTHRIGHT, null,
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
index 831c05f..29aa946 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
@@ -124,6 +124,11 @@
*/
boolean canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill);
+ /**
+ * Returns the maximum duration (in milliseconds) that the specified app can afford the bill,
+ * based on current prices.
+ */
+ long getMaxDurationMs(int userId, @NonNull String pkgName, @NonNull ActionBill bill);
/**
* Register an {@link AffordabilityChangeListener} to track when an app's ability to afford the
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 67d7a95..a2ba75c 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -19,6 +19,8 @@
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
@@ -30,6 +32,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryManagerInternal;
@@ -45,6 +48,7 @@
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArrayMap;
import android.util.SparseSetArray;
import com.android.internal.annotations.GuardedBy;
@@ -81,6 +85,7 @@
private final Handler mHandler;
private final BatteryManagerInternal mBatteryManagerInternal;
private final PackageManager mPackageManager;
+ private final PackageManagerInternal mPackageManagerInternal;
private final Agent mAgent;
private final CompleteEconomicPolicy mCompleteEconomicPolicy;
@@ -95,6 +100,10 @@
@GuardedBy("mLock")
private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();
+ /** Cached mapping of userId+package to their UIDs (for all users) */
+ @GuardedBy("mPackageToUidCache")
+ private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>();
+
private volatile boolean mIsEnabled;
private volatile int mBootPhase;
// In the range [0,100] to represent 0% to 100% battery.
@@ -104,7 +113,6 @@
@GuardedBy("mLock")
private long mLastUnusedReclamationTime;
- @SuppressWarnings("FieldCanBeLocal")
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Nullable
private String getPackageName(Intent intent) {
@@ -159,7 +167,7 @@
public void onAlarm() {
synchronized (mLock) {
mAgent.reclaimUnusedAssetsLocked(DEFAULT_UNUSED_RECLAMATION_PERCENTAGE);
- mLastUnusedReclamationTime = System.currentTimeMillis();
+ mLastUnusedReclamationTime = getCurrentTimeMillis();
scheduleUnusedWealthReclamationLocked();
}
}
@@ -185,6 +193,7 @@
mHandler = new IrsHandler(TareHandlerThread.get().getLooper());
mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class);
mPackageManager = context.getPackageManager();
+ mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mEconomyManagerStub = new EconomyManagerStub();
mCompleteEconomicPolicy = new CompleteEconomicPolicy(this);
mAgent = new Agent(this, mCompleteEconomicPolicy);
@@ -232,10 +241,28 @@
/ 100;
}
+ int getUid(final int userId, @NonNull final String pkgName) {
+ synchronized (mPackageToUidCache) {
+ Integer uid = mPackageToUidCache.get(userId, pkgName);
+ if (uid == null) {
+ uid = mPackageManagerInternal.getPackageUid(pkgName, 0, userId);
+ mPackageToUidCache.add(userId, pkgName, uid);
+ }
+ return uid;
+ }
+ }
+
boolean isEnabled() {
return mIsEnabled;
}
+ boolean isSystem(final int userId, @NonNull String pkgName) {
+ if ("android".equals(pkgName)) {
+ return true;
+ }
+ return UserHandle.isCore(getUid(userId, pkgName));
+ }
+
void onBatteryLevelChanged() {
synchronized (mLock) {
final int newBatteryLevel = getCurrentBatteryLevel();
@@ -261,6 +288,9 @@
Slog.wtf(TAG, "PM couldn't find newly added package: " + pkgName);
return;
}
+ synchronized (mPackageToUidCache) {
+ mPackageToUidCache.add(userId, pkgName, uid);
+ }
synchronized (mLock) {
mPkgCache.add(packageInfo);
mUidToPackageCache.add(uid, pkgName);
@@ -277,6 +307,9 @@
void onPackageRemoved(final int uid, @NonNull final String pkgName) {
final int userId = UserHandle.getUserId(uid);
+ synchronized (mPackageToUidCache) {
+ mPackageToUidCache.delete(userId, pkgName);
+ }
synchronized (mLock) {
mUidToPackageCache.remove(uid, pkgName);
for (int i = 0; i < mPkgCache.size(); ++i) {
@@ -342,7 +375,7 @@
@GuardedBy("mLock")
private void scheduleUnusedWealthReclamationLocked() {
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
final long nextReclamationTime =
Math.max(mLastUnusedReclamationTime + UNUSED_RECLAMATION_PERIOD_MS, now + 30_000);
mHandler.post(() -> {
@@ -447,6 +480,9 @@
mUidToPackageCache.clear();
getContext().unregisterReceiver(mBroadcastReceiver);
}
+ synchronized (mPackageToUidCache) {
+ mPackageToUidCache.clear();
+ }
}
private final class IrsHandler extends Handler {
@@ -514,9 +550,22 @@
}
private final class LocalService implements EconomyManagerInternal {
+ /**
+ * Use an extremely large value to indicate that an app can pay for a bill indefinitely.
+ * The value set here should be large/long enough that there's no reasonable expectation
+ * of a device operating uninterrupted (or in the exact same state) for that period of time.
+ * We intentionally don't use Long.MAX_VALUE to avoid potential overflow if a client
+ * doesn't check the value and just immediately adds it to the current time.
+ */
+ private static final long FOREVER_MS = 27 * 365 * 24 * HOUR_IN_MILLIS;
+
@Override
public void registerAffordabilityChangeListener(int userId, @NonNull String pkgName,
@NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) {
+ if (isSystem(userId, pkgName)) {
+ // The system's affordability never changes.
+ return;
+ }
synchronized (mLock) {
mAgent.registerAffordabilityChangeListenerLocked(userId, pkgName, listener, bill);
}
@@ -525,6 +574,10 @@
@Override
public void unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName,
@NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) {
+ if (isSystem(userId, pkgName)) {
+ // The system's affordability never changes.
+ return;
+ }
synchronized (mLock) {
mAgent.unregisterAffordabilityChangeListenerLocked(userId, pkgName, listener, bill);
}
@@ -535,6 +588,11 @@
if (!mIsEnabled) {
return true;
}
+ if (isSystem(userId, pkgName)) {
+ // The government, I mean the system, can create ARCs as it needs to in order to
+ // operate.
+ return true;
+ }
// TODO: take temp-allowlist into consideration
long requiredBalance = 0;
final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
@@ -552,6 +610,32 @@
}
@Override
+ public long getMaxDurationMs(int userId, @NonNull String pkgName,
+ @NonNull ActionBill bill) {
+ if (!mIsEnabled) {
+ return FOREVER_MS;
+ }
+ if (isSystem(userId, pkgName)) {
+ return FOREVER_MS;
+ }
+ long totalCostPerSecond = 0;
+ final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
+ bill.getAnticipatedActions();
+ for (int i = 0; i < projectedActions.size(); ++i) {
+ AnticipatedAction action = projectedActions.get(i);
+ final long cost =
+ mCompleteEconomicPolicy.getCostOfAction(action.actionId, userId, pkgName);
+ totalCostPerSecond += cost;
+ }
+ if (totalCostPerSecond == 0) {
+ return FOREVER_MS;
+ }
+ synchronized (mLock) {
+ return mAgent.getBalanceLocked(userId, pkgName) * 1000 / totalCostPerSecond;
+ }
+ }
+
+ @Override
public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
@Nullable String tag) {
if (!mIsEnabled) {
@@ -581,7 +665,7 @@
return;
}
final long nowElapsed = SystemClock.elapsedRealtime();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
synchronized (mLock) {
mAgent.stopOngoingActionLocked(userId, pkgName, eventId, tag, nowElapsed, now);
}
@@ -630,6 +714,9 @@
private void dumpInternal(final IndentingPrintWriter pw) {
synchronized (mLock) {
+ pw.print("Is enabled: ");
+ pw.println(mIsEnabled);
+
pw.print("Current battery level: ");
pw.println(mCurrentBatteryLevel);
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
index ae1bf26..76543d7 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
@@ -19,6 +19,7 @@
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static com.android.server.tare.TareUtils.dumpTime;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
import static com.android.server.tare.TareUtils.narcToString;
import android.annotation.NonNull;
@@ -109,8 +110,8 @@
/** Deletes transactions that are older than {@code minAgeMs}. */
void removeOldTransactions(long minAgeMs) {
- final long cutoff = System.currentTimeMillis() - minAgeMs;
- while (mTransactions.get(0).endTimeMs <= cutoff) {
+ final long cutoff = getCurrentTimeMillis() - minAgeMs;
+ while (mTransactions.size() > 0 && mTransactions.get(0).endTimeMs <= cutoff) {
mTransactions.remove(0);
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
index 92a2014a..67a3dc6 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
@@ -20,7 +20,6 @@
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.IUidObserver;
-import android.content.pm.PackageManagerInternal;
import android.os.RemoteException;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -28,7 +27,6 @@
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
-import com.android.server.LocalServices;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -56,7 +54,6 @@
private final Object mLock = new Object();
private final InternalResourceService mIrs;
- private final PackageManagerInternal mPackageManagerInternal;
/** Cached mapping of userId+package to their UIDs (for all users) */
private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>();
@@ -105,7 +102,6 @@
ProcessStateModifier(@NonNull InternalResourceService irs) {
super();
mIrs = irs;
- mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
}
@Override
@@ -143,7 +139,7 @@
final int procState;
synchronized (mLock) {
procState = mUidProcStateBucketCache.get(
- getUidLocked(userId, pkgName), PROC_STATE_BUCKET_NONE);
+ mIrs.getUid(userId, pkgName), PROC_STATE_BUCKET_NONE);
}
switch (procState) {
case PROC_STATE_BUCKET_TOP:
@@ -166,15 +162,6 @@
pw.println(mUidProcStateBucketCache);
}
- @GuardedBy("mLock")
- private int getUidLocked(final int userId, @NonNull final String pkgName) {
- if (!mPackageToUidCache.contains(userId, pkgName)) {
- mPackageToUidCache.add(userId, pkgName,
- mPackageManagerInternal.getPackageUid(pkgName, 0, userId));
- }
- return mPackageToUidCache.get(userId, pkgName);
- }
-
@ProcStateBucket
private int getProcStateBucket(int procState) {
if (procState <= ActivityManager.PROCESS_STATE_TOP) {
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
index 2d72f56..1e047aa 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
@@ -20,7 +20,10 @@
import android.annotation.SuppressLint;
import android.util.IndentingPrintWriter;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.text.SimpleDateFormat;
+import java.time.Clock;
class TareUtils {
private static final long NARC_IN_ARC = 1_000_000_000L;
@@ -29,6 +32,9 @@
private static final SimpleDateFormat sDumpDateFormat =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ @VisibleForTesting
+ static Clock sSystemClock = Clock.systemUTC();
+
static long arcToNarc(int arcs) {
return arcs * NARC_IN_ARC;
}
@@ -37,6 +43,10 @@
pw.print(sDumpDateFormat.format(time));
}
+ static long getCurrentTimeMillis() {
+ return sSystemClock.millis();
+ }
+
static int narcToArc(long narcs) {
return (int) (narcs / NARC_IN_ARC);
}
@@ -59,4 +69,10 @@
sb.append(" ARCs");
return sb.toString();
}
+
+ /** Returns a standardized format for printing userId+pkgName combinations. */
+ @NonNull
+ static String appToString(int userId, String pkgName) {
+ return "<" + userId + ">" + pkgName;
+ }
}
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index b2b66c2..3534624 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -71,7 +71,7 @@
"libui",
"libjnigraphics",
"libEGL",
- "libGLESv1_CM",
+ "libGLESv2",
"libgui",
],
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 3109c5c..6e27aff 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -52,9 +52,8 @@
#include <gui/DisplayEventReceiver.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
#include <EGL/eglext.h>
#include "BootAnimation.h"
@@ -108,6 +107,56 @@
static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays";
static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
static constexpr size_t TEXT_POS_LEN_MAX = 16;
+static const char U_TEXTURE[] = "uTexture";
+static const char U_FADE[] = "uFade";
+static const char U_CROP_AREA[] = "uCropArea";
+static const char A_UV[] = "aUv";
+static const char A_POSITION[] = "aPosition";
+static const char VERTEX_SHADER_SOURCE[] = R"(
+ precision mediump float;
+ attribute vec4 aPosition;
+ attribute highp vec2 aUv;
+ varying highp vec2 vUv;
+ void main() {
+ gl_Position = aPosition;
+ vUv = aUv;
+ })";
+static const char IMAGE_FRAG_SHADER_SOURCE[] = R"(
+ precision mediump float;
+ uniform sampler2D uTexture;
+ uniform float uFade;
+ varying highp vec2 vUv;
+ void main() {
+ vec4 color = texture2D(uTexture, vUv);
+ gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade);
+ })";
+static const char TEXT_FRAG_SHADER_SOURCE[] = R"(
+ precision mediump float;
+ uniform sampler2D uTexture;
+ uniform vec4 uCropArea;
+ varying highp vec2 vUv;
+ void main() {
+ vec2 uv = vec2(mix(uCropArea.x, uCropArea.z, vUv.x),
+ mix(uCropArea.y, uCropArea.w, vUv.y));
+ gl_FragColor = texture2D(uTexture, uv);
+ })";
+
+static GLfloat quadPositions[] = {
+ -0.5f, -0.5f,
+ +0.5f, -0.5f,
+ +0.5f, +0.5f,
+ +0.5f, +0.5f,
+ -0.5f, +0.5f,
+ -0.5f, -0.5f
+};
+static GLfloat quadUVs[] = {
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f
+};
// ---------------------------------------------------------------------------
@@ -209,7 +258,6 @@
const int w = bitmapInfo.width;
const int h = bitmapInfo.height;
- GLint crop[4] = { 0, h, w, -h };
texture->w = w;
texture->h = h;
@@ -237,11 +285,10 @@
break;
}
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return NO_ERROR;
}
@@ -263,7 +310,6 @@
const int w = bitmapInfo.width;
const int h = bitmapInfo.height;
- GLint crop[4] = { 0, h, w, -h };
int tw = 1 << (31 - __builtin_clz(w));
int th = 1 << (31 - __builtin_clz(h));
if (tw < w) tw <<= 1;
@@ -297,7 +343,10 @@
break;
}
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
*width = w;
*height = h;
@@ -470,7 +519,9 @@
eglInitialize(display, nullptr, nullptr);
EGLConfig config = getEglConfig(display);
EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
- EGLContext context = eglCreateContext(display, config, nullptr, nullptr);
+ // Initialize egl context with client version number 2.0.
+ EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes);
EGLint w, h;
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
@@ -503,11 +554,6 @@
void BootAnimation::projectSceneToWindow() {
glViewport(0, 0, mWidth, mHeight);
glScissor(0, 0, mWidth, mHeight);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrthof(0, static_cast<float>(mWidth), 0, static_cast<float>(mHeight), -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
}
void BootAnimation::resizeSurface(int newWidth, int newHeight) {
@@ -600,8 +646,68 @@
}
}
+GLuint compileShader(GLenum shaderType, const GLchar *source) {
+ GLuint shader = glCreateShader(shaderType);
+ glShaderSource(shader, 1, &source, 0);
+ glCompileShader(shader);
+ GLint isCompiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
+ if (isCompiled == GL_FALSE) {
+ SLOGE("Compile shader failed. Shader type: %d", shaderType);
+ return 0;
+ }
+ return shader;
+}
+
+GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) {
+ GLuint program = glCreateProgram();
+ glAttachShader(program, vertexShader);
+ glAttachShader(program, fragmentShader);
+ glLinkProgram(program);
+ GLint isLinked = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
+ if (isLinked == GL_FALSE) {
+ SLOGE("Linking shader failed. Shader handles: vert %d, frag %d",
+ vertexShader, fragmentShader);
+ return 0;
+ }
+ return program;
+}
+
+void BootAnimation::initShaders() {
+ GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE);
+ GLuint imageFragmentShader =
+ compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE);
+ GLuint textFragmentShader =
+ compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE);
+
+ // Initialize image shader.
+ mImageShader = linkShader(vertexShader, imageFragmentShader);
+ GLint positionLocation = glGetAttribLocation(mImageShader, A_POSITION);
+ GLint uvLocation = glGetAttribLocation(mImageShader, A_UV);
+ mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE);
+ mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE);
+ glEnableVertexAttribArray(positionLocation);
+ glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions);
+ glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs);
+ glEnableVertexAttribArray(uvLocation);
+
+ // Initialize text shader.
+ mTextShader = linkShader(vertexShader, textFragmentShader);
+ positionLocation = glGetAttribLocation(mTextShader, A_POSITION);
+ uvLocation = glGetAttribLocation(mTextShader, A_UV);
+ mTextTextureLocation = glGetUniformLocation(mTextShader, U_TEXTURE);
+ mTextCropAreaLocation = glGetUniformLocation(mTextShader, U_CROP_AREA);
+ glEnableVertexAttribArray(positionLocation);
+ glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions);
+ glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs);
+ glEnableVertexAttribArray(uvLocation);
+}
+
bool BootAnimation::threadLoop() {
bool result;
+ initShaders();
+
// We have no bootanimation file, so we use the stock android logo
// animation.
if (mZipFileName.isEmpty()) {
@@ -623,6 +729,8 @@
}
bool BootAnimation::android() {
+ glActiveTexture(GL_TEXTURE0);
+
SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
@@ -631,19 +739,14 @@
mCallbacks->init({});
// clear screen
- glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(mDisplay, mSurface);
- glEnable(GL_TEXTURE_2D);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
// Blend state
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
const nsecs_t startTime = systemTime();
do {
@@ -666,12 +769,12 @@
glEnable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
- glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h);
- glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);
+ drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h);
+ drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h);
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
- glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
+ drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h);
EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
if (res == EGL_FALSE)
@@ -798,10 +901,10 @@
status = initTexture(font->map, &font->texture.w, &font->texture.h);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else if (fallback != nullptr) {
status = initTexture(&font->texture, mAssets, fallback);
} else {
@@ -816,40 +919,11 @@
return status;
}
-void BootAnimation::fadeFrame(const int frameLeft, const int frameBottom, const int frameWidth,
- const int frameHeight, const Animation::Part& part,
- const int fadedFramesCount) {
- glEnable(GL_BLEND);
- glEnableClientState(GL_VERTEX_ARRAY);
- glDisable(GL_TEXTURE_2D);
- // avoid creating a hole due to mixing result alpha with GL_REPLACE texture
- glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
-
- const float alpha = static_cast<float>(fadedFramesCount) / part.framesToFadeCount;
- glColor4f(part.backgroundColor[0], part.backgroundColor[1], part.backgroundColor[2], alpha);
-
- const float frameStartX = static_cast<float>(frameLeft);
- const float frameStartY = static_cast<float>(frameBottom);
- const float frameEndX = frameStartX + frameWidth;
- const float frameEndY = frameStartY + frameHeight;
- const GLfloat frameRect[] = {
- frameStartX, frameStartY,
- frameEndX, frameStartY,
- frameEndX, frameEndY,
- frameStartX, frameEndY
- };
- glVertexPointer(2, GL_FLOAT, 0, frameRect);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_TEXTURE_2D);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisable(GL_BLEND);
-}
-
void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) {
glEnable(GL_BLEND); // Allow us to draw on top of the animation
glBindTexture(GL_TEXTURE_2D, font.texture.name);
+ glUseProgram(mTextShader);
+ glUniform1i(mTextTextureLocation, 0);
const int len = strlen(str);
const int strWidth = font.char_width * len;
@@ -865,8 +939,6 @@
*y = mHeight + *y - font.char_height;
}
- int cropRect[4] = { 0, 0, font.char_width, -font.char_height };
-
for (int i = 0; i < len; i++) {
char c = str[i];
@@ -878,13 +950,13 @@
const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters
const int row = charPos / FONT_NUM_COLS;
const int col = charPos % FONT_NUM_COLS;
- cropRect[0] = col * font.char_width; // Left of column
- cropRect[1] = row * font.char_height * 2; // Top of row
- // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line
- cropRect[1] += bold ? 2 * font.char_height : font.char_height;
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
-
- glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height);
+ // Bold fonts are expected in the second half of each row.
+ float v0 = (row + (bold ? 0.5f : 0.0f)) / FONT_NUM_ROWS;
+ float u0 = ((float)col) / FONT_NUM_COLS;
+ float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2;
+ float u1 = u0 + 1.0f / FONT_NUM_COLS;
+ glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1);
+ drawTexturedQuad(*x, *y, font.char_width, font.char_height);
*x += font.char_width;
}
@@ -1166,19 +1238,16 @@
// Blend required to draw time on top of animation frames.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
- glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
bool clockFontInitialized = false;
if (mClockEnabled) {
clockFontInitialized =
@@ -1218,6 +1287,34 @@
(lastDisplayedProgress == 0 || lastDisplayedProgress == 100);
}
+// Linear mapping from range <a1, a2> to range <b1, b2>
+float mapLinear(float x, float a1, float a2, float b1, float b2) {
+ return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
+}
+
+void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) {
+ // Map coordinates from screen space to world space.
+ float x0 = mapLinear(xStart, 0, mWidth, -1, 1);
+ float y0 = mapLinear(yStart, 0, mHeight, -1, 1);
+ float x1 = mapLinear(xStart + width, 0, mWidth, -1, 1);
+ float y1 = mapLinear(yStart + height, 0, mHeight, -1, 1);
+ // Update quad vertex positions.
+ quadPositions[0] = x0;
+ quadPositions[1] = y0;
+ quadPositions[2] = x1;
+ quadPositions[3] = y0;
+ quadPositions[4] = x1;
+ quadPositions[5] = y1;
+ quadPositions[6] = x1;
+ quadPositions[7] = y1;
+ quadPositions[8] = x0;
+ quadPositions[9] = y1;
+ quadPositions[10] = x0;
+ quadPositions[11] = y0;
+ glDrawArrays(GL_TRIANGLES, 0,
+ sizeof(quadPositions) / sizeof(quadPositions[0]) / 2);
+}
+
bool BootAnimation::playAnimation(const Animation& animation) {
const size_t pcount = animation.parts.size();
nsecs_t frameDuration = s2ns(1) / animation.fps;
@@ -1230,7 +1327,6 @@
for (size_t i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
const size_t fcount = part.frames.size();
- glBindTexture(GL_TEXTURE_2D, 0);
// Handle animation package
if (part.animation != nullptr) {
@@ -1272,12 +1368,8 @@
if (r > 0) {
glBindTexture(GL_TEXTURE_2D, frame.tid);
} else {
- if (part.count != 1) {
- glGenTextures(1, &frame.tid);
- glBindTexture(GL_TEXTURE_2D, frame.tid);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
+ glGenTextures(1, &frame.tid);
+ glBindTexture(GL_TEXTURE_2D, frame.tid);
int w, h;
initTexture(frame.map, &w, &h);
}
@@ -1300,16 +1392,21 @@
// specify the y center as ceiling((mHeight - frame.trimHeight) / 2)
// which is equivalent to mHeight - (yc + frame.trimHeight)
const int frameDrawY = mHeight - (yc + frame.trimHeight);
- glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight);
+ float fade = 0;
// if the part hasn't been stopped yet then continue fading if necessary
if (exitPending() && part.hasFadingPhase()) {
- fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part,
- ++fadedFramesCount);
+ fade = static_cast<float>(++fadedFramesCount) / part.framesToFadeCount;
if (fadedFramesCount >= part.framesToFadeCount) {
fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading
}
}
+ glUseProgram(mImageShader);
+ glUniform1i(mImageTextureLocation, 0);
+ glUniform1f(mImageFadeLocation, fade);
+ glEnable(GL_BLEND);
+ drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight);
+ glDisable(GL_BLEND);
if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f8a31c6..7b616d9 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -31,7 +31,7 @@
#include <binder/IBinder.h>
#include <EGL/egl.h>
-#include <GLES/gl.h>
+#include <GLES2/gl2.h>
namespace android {
@@ -166,6 +166,7 @@
status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
status_t initTexture(FileMap* map, int* width, int* height);
status_t initFont(Font* font, const char* fallback);
+ void initShaders();
bool android();
bool movie();
void drawText(const char* str, const Font& font, bool bold, int* x, int* y);
@@ -173,6 +174,7 @@
void drawProgress(int percent, const Font& font, const int xPos, const int yPos);
void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight,
const Animation::Part& part, int fadedFramesCount);
+ void drawTexturedQuad(float xStart, float yStart, float width, float height);
bool validClock(const Animation::Part& part);
Animation* loadAnimation(const String8&);
bool playAnimation(const Animation&);
@@ -218,6 +220,12 @@
sp<TimeCheckThread> mTimeCheckThread = nullptr;
sp<Callbacks> mCallbacks;
Animation* mAnimation = nullptr;
+ GLuint mImageShader;
+ GLuint mTextShader;
+ GLuint mImageFadeLocation;
+ GLuint mImageTextureLocation;
+ GLuint mTextCropAreaLocation;
+ GLuint mTextTextureLocation;
};
// ---------------------------------------------------------------------------
diff --git a/core/api/current.txt b/core/api/current.txt
index 4c1476c..396c080 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25266,13 +25266,17 @@
public final class MediaSessionManager {
method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName);
method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, @Nullable android.os.Handler);
+ method public void addOnMediaKeyEventSessionChangedListener(@NonNull android.content.ComponentName, @NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener, @NonNull android.os.Handler);
method @NonNull public java.util.List<android.media.session.MediaController> getActiveSessions(@Nullable android.content.ComponentName);
+ method @Nullable public android.media.session.MediaSession.Token getMediaKeyEventSession(@NonNull android.content.ComponentName);
+ method @NonNull public String getMediaKeyEventSessionPackageName(@NonNull android.content.ComponentName);
method @NonNull public java.util.List<android.media.Session2Token> getSession2Tokens();
method public boolean isTrustedForMediaControl(@NonNull android.media.session.MediaSessionManager.RemoteUserInfo);
method @Deprecated public void notifySession2Created(@NonNull android.media.Session2Token);
method public void removeOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
+ method public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
method public void removeOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
}
@@ -25280,6 +25284,10 @@
method public void onActiveSessionsChanged(@Nullable java.util.List<android.media.session.MediaController>);
}
+ public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
+ method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
+ }
+
public static interface MediaSessionManager.OnSession2TokensChangedListener {
method public void onSession2TokensChanged(@NonNull java.util.List<android.media.Session2Token>);
}
@@ -31676,6 +31684,7 @@
method public boolean isDeviceIdleMode();
method public boolean isIgnoringBatteryOptimizations(String);
method public boolean isInteractive();
+ method public boolean isLightDeviceIdleMode();
method public boolean isPowerSaveMode();
method public boolean isRebootingUserspaceSupported();
method @Deprecated public boolean isScreenOn();
@@ -31686,6 +31695,7 @@
method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
+ field public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED = "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
field public static final String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
field @Deprecated public static final int FULL_WAKE_LOCK = 26; // 0x1a
field public static final int LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2; // 0x2
@@ -34824,6 +34834,7 @@
}
public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns {
+ field public static final String ACTION_SET_DEFAULT_ACCOUNT = "android.provider.action.SET_DEFAULT_ACCOUNT";
field public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting";
field public static final android.net.Uri CONTENT_URI;
@@ -51933,7 +51944,7 @@
method public boolean finishComposingText();
method public int getCursorCapsMode(int);
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
- method public android.os.Handler getHandler();
+ method @Nullable public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
method @Nullable public default android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 96c990d..1eec826 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5587,7 +5587,6 @@
method @Nullable @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.media.session.MediaSession.Token getMediaKeyEventSession();
method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public String getMediaKeyEventSessionPackageName();
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventDispatchedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
- method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
}
@@ -5596,10 +5595,6 @@
method public void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @Nullable android.media.session.MediaSession.Token);
}
- public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
- method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
- }
-
public static interface MediaSessionManager.OnMediaKeyListener {
method public boolean onMediaKey(android.view.KeyEvent);
}
@@ -7028,13 +7023,13 @@
field public static final long FEC_23_36 = 268435456L; // 0x10000000L
field public static final long FEC_25_36 = 536870912L; // 0x20000000L
field public static final long FEC_26_45 = 1073741824L; // 0x40000000L
- field public static final long FEC_28_45 = -2147483648L; // 0xffffffff80000000L
- field public static final long FEC_29_45 = 1L; // 0x1L
+ field public static final long FEC_28_45 = 2147483648L; // 0x80000000L
+ field public static final long FEC_29_45 = 4294967296L; // 0x100000000L
field public static final long FEC_2_3 = 32L; // 0x20L
field public static final long FEC_2_5 = 64L; // 0x40L
field public static final long FEC_2_9 = 128L; // 0x80L
- field public static final long FEC_31_45 = 2L; // 0x2L
- field public static final long FEC_32_45 = 4L; // 0x4L
+ field public static final long FEC_31_45 = 8589934592L; // 0x200000000L
+ field public static final long FEC_32_45 = 17179869184L; // 0x400000000L
field public static final long FEC_3_4 = 256L; // 0x100L
field public static final long FEC_3_5 = 512L; // 0x200L
field public static final long FEC_4_15 = 2048L; // 0x800L
@@ -7042,7 +7037,7 @@
field public static final long FEC_5_6 = 4096L; // 0x1000L
field public static final long FEC_5_9 = 8192L; // 0x2000L
field public static final long FEC_6_7 = 16384L; // 0x4000L
- field public static final long FEC_77_90 = 8L; // 0x8L
+ field public static final long FEC_77_90 = 34359738368L; // 0x800000000L
field public static final long FEC_7_15 = 131072L; // 0x20000L
field public static final long FEC_7_8 = 32768L; // 0x8000L
field public static final long FEC_7_9 = 65536L; // 0x10000L
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 45db0f6..fd6589c 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -2112,7 +2112,8 @@
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
- + "; have you declared this activity in your AndroidManifest.xml?");
+ + "; have you declared this activity in your AndroidManifest.xml"
+ + ", or does your intent not match its declared <intent-filter>?");
throw new ActivityNotFoundException(
"No Activity found to handle " + intent);
case ActivityManager.START_PERMISSION_DENIED:
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 27db25d..9a37d04 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -13736,8 +13736,6 @@
*
* It is recommended that the Enterprise ID is at least 6 characters long, and no more than
* 64 characters.
- * This API is supposed to be called only after the boot phase is complete,
- * throws {@link IllegalStateException} if called before boot phase is complete.
*
* @param enterpriseId An identifier of the organization this work profile or device is
* enrolled into.
diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java
index 266e33a..5694ca8 100644
--- a/core/java/android/appwidget/AppWidgetManagerInternal.java
+++ b/core/java/android/appwidget/AppWidgetManagerInternal.java
@@ -19,8 +19,6 @@
import android.annotation.Nullable;
import android.util.ArraySet;
-import java.util.Set;
-
/**
* App widget manager local system service interface.
*
@@ -44,16 +42,4 @@
* @param userId The user that is being unlocked.
*/
public abstract void unlockUser(int userId);
-
- /**
- * Updates all widgets, applying changes to Runtime Resource Overlay affecting the specified
- * target packages.
- *
- * @param packageNames The names of all target packages for which an overlay was modified
- * @param userId The user for which overlay modifications occurred.
- * @param updateFrameworkRes Whether or not an overlay affected the values of framework
- * resources.
- */
- public abstract void applyResourceOverlaysToWidgets(Set<String> packageNames, int userId,
- boolean updateFrameworkRes);
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index a741f96..c714f507 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -745,9 +745,6 @@
if (Binder.getCallingPid() == Process.myPid()) {
return PermissionChecker.PERMISSION_GRANTED;
}
- if (!attributionSource.checkCallingUid()) {
- return PermissionChecker.PERMISSION_HARD_DENIED;
- }
return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(getContext(),
permission, -1, new AttributionSource(getContext().getAttributionSource(),
attributionSource), /*message*/ null);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bed0383..29ce397 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -55,6 +55,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.overlay.OverlayPaths;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.split.SplitAssetLoader;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.ApkAssets;
@@ -7425,7 +7427,7 @@
mCompileSdkVersionCodename = dest.readString();
mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
- mKeySetMapping = readKeySetMapping(dest);
+ mKeySetMapping = ParsingPackageUtils.readKeySetMapping(dest);
cpuAbiOverride = dest.readString();
use32bitAbi = (dest.readInt() == 1);
@@ -7551,73 +7553,13 @@
dest.writeInt(mCompileSdkVersion);
dest.writeString(mCompileSdkVersionCodename);
dest.writeArraySet(mUpgradeKeySets);
- writeKeySetMapping(dest, mKeySetMapping);
+ ParsingPackageUtils.writeKeySetMapping(dest, mKeySetMapping);
dest.writeString(cpuAbiOverride);
dest.writeInt(use32bitAbi ? 1 : 0);
dest.writeByteArray(restrictUpdateHash);
dest.writeInt(visibleToInstantApps ? 1 : 0);
}
- /**
- * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
- */
- private static void writeKeySetMapping(
- Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
- if (keySetMapping == null) {
- dest.writeInt(-1);
- return;
- }
-
- final int N = keySetMapping.size();
- dest.writeInt(N);
-
- for (int i = 0; i < N; i++) {
- dest.writeString(keySetMapping.keyAt(i));
- ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
- if (keys == null) {
- dest.writeInt(-1);
- continue;
- }
-
- final int M = keys.size();
- dest.writeInt(M);
- for (int j = 0; j < M; j++) {
- dest.writeSerializable(keys.valueAt(j));
- }
- }
- }
-
- /**
- * Reads a keyset mapping from the given parcel at the given data position. May return
- * {@code null} if the serialized mapping was {@code null}.
- */
- private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
- final int N = in.readInt();
- if (N == -1) {
- return null;
- }
-
- ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
- for (int i = 0; i < N; ++i) {
- String key = in.readString();
- final int M = in.readInt();
- if (M == -1) {
- keySetMapping.put(key, null);
- continue;
- }
-
- ArraySet<PublicKey> keys = new ArraySet<>(M);
- for (int j = 0; j < M; ++j) {
- PublicKey pk = (PublicKey) in.readSerializable();
- keys.add(pk);
- }
-
- keySetMapping.put(key, keys);
- }
-
- return keySetMapping;
- }
-
public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
public Package createFromParcel(Parcel in) {
return new Package(in);
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index 9fee7bb..f2a6a5c 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -535,7 +535,7 @@
ai.setMaxAspectRatio(maxAspectRatio != null ? maxAspectRatio : 0f);
Float minAspectRatio = a.getMinAspectRatio();
ai.setMinAspectRatio(minAspectRatio != null ? minAspectRatio : 0f);
- ai.supportsSizeChanges = a.getSupportsSizeChanges();
+ ai.supportsSizeChanges = a.isSupportsSizeChanges();
ai.requestedVrComponent = a.getRequestedVrComponent();
ai.rotationAnimation = a.getRotationAnimation();
ai.colorMode = a.getColorMode();
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 72cc929..d6e1ac9 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -360,7 +360,7 @@
ParsingPackage setCompileSdkVersion(int compileSdkVersion);
- ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename);
+ ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName);
ParsingPackage setAttributionsAreUserVisible(boolean attributionsAreUserVisible);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 0db6546..f0d95d9 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -553,7 +553,7 @@
setCompileSdkVersion(manifestArray.getInteger(
R.styleable.AndroidManifest_compileSdkVersion, 0));
- setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
+ setCompileSdkVersionCodeName(manifestArray.getNonConfigurationString(
R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
setIsolatedSplitLoading(manifestArray.getBoolean(
@@ -2686,8 +2686,8 @@
}
@Override
- public ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename) {
- this.compileSdkVersionCodeName = compileSdkVersionCodename;
+ public ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName) {
+ this.compileSdkVersionCodeName = compileSdkVersionCodeName;
return this;
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivity.java b/core/java/android/content/pm/parsing/component/ParsedActivity.java
index 73ee132..adb6b76 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivity.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivity.java
@@ -23,6 +23,7 @@
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
@@ -423,6 +424,7 @@
}
}
+ @NonNull
public static final Parcelable.Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
@Override
public ParsedActivity createFromParcel(Parcel source) {
@@ -513,10 +515,6 @@
return minAspectRatio;
}
- public boolean getSupportsSizeChanges() {
- return supportsSizeChanges;
- }
-
@Nullable
public String getRequestedVrComponent() {
return requestedVrComponent;
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponent.java b/core/java/android/content/pm/parsing/component/ParsedComponent.java
index 3c0f097..838adfd 100644
--- a/core/java/android/content/pm/parsing/component/ParsedComponent.java
+++ b/core/java/android/content/pm/parsing/component/ParsedComponent.java
@@ -43,8 +43,8 @@
/** @hide */
public abstract class ParsedComponent implements Parcelable {
- private static ParsedIntentInfo.ListParceler sForIntentInfos = Parcelling.Cache.getOrCreate(
- ParsedIntentInfo.ListParceler.class);
+ private static final ParsedIntentInfo.ListParceler sForIntentInfos =
+ Parcelling.Cache.getOrCreate(ParsedIntentInfo.ListParceler.class);
@NonNull
@DataClass.ParcelWith(ForInternedString.class)
diff --git a/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java b/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
index 65ff472..4178920 100644
--- a/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
+++ b/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
@@ -18,6 +18,7 @@
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.Parcel;
@@ -94,6 +95,7 @@
this.functionalTest = in.readByte() != 0;
}
+ @NonNull
public static final Parcelable.Creator<ParsedInstrumentation> CREATOR =
new Parcelable.Creator<ParsedInstrumentation>() {
@Override
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
index 01ee0f4..59d4a95 100644
--- a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
@@ -16,6 +16,7 @@
package android.content.pm.parsing.component;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.IntentFilter;
import android.os.Parcel;
@@ -58,6 +59,7 @@
item.writeIntentInfoToParcel(dest, parcelFlags);
}
+ @NonNull
@Override
public ParsedIntentInfo unparcel(Parcel source) {
return new ParsedIntentInfo(source);
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermission.java b/core/java/android/content/pm/parsing/component/ParsedPermission.java
index 50bc3d9..0f82941 100644
--- a/core/java/android/content/pm/parsing/component/ParsedPermission.java
+++ b/core/java/android/content/pm/parsing/component/ParsedPermission.java
@@ -16,6 +16,7 @@
package android.content.pm.parsing.component;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PermissionInfo;
import android.os.Parcel;
@@ -167,6 +168,7 @@
this.knownCerts = sForStringSet.unparcel(in);
}
+ @NonNull
public static final Parcelable.Creator<ParsedPermission> CREATOR =
new Parcelable.Creator<ParsedPermission>() {
@Override
diff --git a/core/java/android/content/pm/parsing/component/ParsedProcess.java b/core/java/android/content/pm/parsing/component/ParsedProcess.java
index c39d6b1..fe10225 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProcess.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProcess.java
@@ -19,7 +19,6 @@
import static java.util.Collections.emptySet;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/parsing/component/ParsedProvider.java b/core/java/android/content/pm/parsing/component/ParsedProvider.java
index ebf85f7..9a12b48 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProvider.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProvider.java
@@ -169,6 +169,7 @@
this.pathPermissions = in.createTypedArray(PathPermission.CREATOR);
}
+ @NonNull
public static final Parcelable.Creator<ParsedProvider> CREATOR = new Creator<ParsedProvider>() {
@Override
public ParsedProvider createFromParcel(Parcel source) {
diff --git a/core/java/android/content/pm/parsing/component/ParsedService.java b/core/java/android/content/pm/parsing/component/ParsedService.java
index 471d346..5499a13 100644
--- a/core/java/android/content/pm/parsing/component/ParsedService.java
+++ b/core/java/android/content/pm/parsing/component/ParsedService.java
@@ -18,6 +18,7 @@
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.Parcel;
@@ -83,6 +84,7 @@
this.permission = sForInternedString.unparcel(in);
}
+ @NonNull
public static final Parcelable.Creator<ParsedService> CREATOR = new Creator<ParsedService>() {
@Override
public ParsedService createFromParcel(Parcel source) {
diff --git a/core/java/android/hardware/camera2/MultiResolutionImageReader.java b/core/java/android/hardware/camera2/MultiResolutionImageReader.java
index 3af1b5b..0dbf29d 100644
--- a/core/java/android/hardware/camera2/MultiResolutionImageReader.java
+++ b/core/java/android/hardware/camera2/MultiResolutionImageReader.java
@@ -91,7 +91,7 @@
* </p>
* <p>
* The {@code maxImages} parameter determines the maximum number of
- * {@link Image} objects that can be be acquired from each of the {@code ImageReader}
+ * {@link Image} objects that can be acquired from each of the {@code ImageReader}
* within the {@code MultiResolutionImageReader}. However, requesting more buffers will
* use up more memory, so it is important to use only the minimum number necessary. The
* application is strongly recommended to acquire no more than {@code maxImages} images
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 8fd9a6a..196134b 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1720,21 +1720,21 @@
new SetCommand() {
@Override
public <T> void setValue(CameraMetadataNative metadata, T value) {
- metadata.setAWBRegions((MeteringRectangle[]) value);
+ metadata.setAWBRegions(value);
}
});
sSetCommandMap.put(CaptureRequest.CONTROL_AF_REGIONS.getNativeKey(),
new SetCommand() {
@Override
public <T> void setValue(CameraMetadataNative metadata, T value) {
- metadata.setAFRegions((MeteringRectangle[]) value);
+ metadata.setAFRegions(value);
}
});
sSetCommandMap.put(CaptureRequest.CONTROL_AE_REGIONS.getNativeKey(),
new SetCommand() {
@Override
public <T> void setValue(CameraMetadataNative metadata, T value) {
- metadata.setAERegions((MeteringRectangle[]) value);
+ metadata.setAERegions(value);
}
});
}
@@ -1815,30 +1815,33 @@
return true;
}
- private <T> boolean setAFRegions(MeteringRectangle[] afRegions) {
+ private <T> boolean setAFRegions(T afRegions) {
if (afRegions == null) {
return false;
}
setBase(CaptureRequest.CONTROL_AF_REGIONS_SET, true);
- setBase(CaptureRequest.CONTROL_AF_REGIONS, afRegions);
+ // The cast to CaptureRequest.Key is needed since java does not support template
+ // specialization and we need to route this method to
+ // setBase(CaptureRequest.Key<T> key, T value)
+ setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AF_REGIONS, afRegions);
return true;
}
- private <T> boolean setAERegions(MeteringRectangle[] aeRegions) {
+ private <T> boolean setAERegions(T aeRegions) {
if (aeRegions == null) {
return false;
}
setBase(CaptureRequest.CONTROL_AE_REGIONS_SET, true);
- setBase(CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
+ setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
return true;
}
- private <T> boolean setAWBRegions(MeteringRectangle[] awbRegions) {
+ private <T> boolean setAWBRegions(T awbRegions) {
if (awbRegions == null) {
return false;
}
setBase(CaptureRequest.CONTROL_AWB_REGIONS_SET, true);
- setBase(CaptureRequest.CONTROL_AWB_REGIONS, awbRegions);
+ setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AWB_REGIONS, awbRegions);
return true;
}
diff --git a/core/java/android/hardware/camera2/params/InputConfiguration.java b/core/java/android/hardware/camera2/params/InputConfiguration.java
index 8dfc0a7b..70c85a1 100644
--- a/core/java/android/hardware/camera2/params/InputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/InputConfiguration.java
@@ -42,7 +42,7 @@
private final boolean mIsMultiResolution;
/**
- * Create an input configration with the width, height, and user-defined format.
+ * Create an input configuration with the width, height, and user-defined format.
*
* <p>Images of a user-defined format are accessible by applications. Use
* {@link android.hardware.camera2.CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP}
@@ -64,7 +64,7 @@
}
/**
- * Create an input configration with the format and a list of multi-resolution input stream
+ * Create an input configuration with the format and a list of multi-resolution input stream
* info.
*
* <p>Use {@link
@@ -108,7 +108,7 @@
}
/**
- * Get the width of this input configration.
+ * Get the width of this input configuration.
*
* @return width of this input configuration.
*/
@@ -117,7 +117,7 @@
}
/**
- * Get the height of this input configration.
+ * Get the height of this input configuration.
*
* @return height of this input configuration.
*/
@@ -126,7 +126,7 @@
}
/**
- * Get the format of this input configration.
+ * Get the format of this input configuration.
*
* @return format of this input configuration.
*/
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index f38271a..403f55c 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -34,6 +34,7 @@
import com.android.internal.os.IDropBoxManagerService;
+import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
@@ -257,7 +258,8 @@
} else {
return null;
}
- return (mFlags & IS_GZIPPED) != 0 ? new GZIPInputStream(is) : is;
+ return (mFlags & IS_GZIPPED) != 0
+ ? new GZIPInputStream(new BufferedInputStream(is)) : is;
}
public static final @android.annotation.NonNull Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator() {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 3aa0bcb..2f66a39 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -2092,9 +2092,7 @@
* when light idle mode restrictions are being actively applied; it will return false if the
* device is in a long-term idle mode but currently running a maintenance window where
* restrictions have been lifted.
- * @hide
*/
- @UnsupportedAppUsage
public boolean isLightDeviceIdleMode() {
try {
return mService.isLightDeviceIdleMode();
@@ -2555,9 +2553,7 @@
/**
* Intent that is broadcast when the state of {@link #isLightDeviceIdleMode()} changes.
* This broadcast is only sent to registered receivers.
- * @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED
= "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b3d60a5..570d73d 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8588,6 +8588,15 @@
* Type: INTEGER
*/
public static final String UNGROUPED_WITH_PHONES = "summ_phones";
+
+ /**
+ * Flag indicating if the account is the default account for new contacts. At most one
+ * account has this flag set at a time. It can only be set to 1 on a row with null data set.
+ * <p>
+ * Type: INTEGER (boolean)
+ * @hide
+ */
+ String IS_DEFAULT = "x_is_default";
}
/**
@@ -8681,6 +8690,13 @@
* The MIME-type of {@link #CONTENT_URI} providing a single setting.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
+
+ /**
+ * Action used to launch the UI to set the default account for new contacts.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SET_DEFAULT_ACCOUNT =
+ "android.provider.action.SET_DEFAULT_ACCOUNT";
}
/**
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 9cb0d1f..e7ff978 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1463,10 +1463,10 @@
return false;
}
final Configuration config = mResources.getConfiguration();
- // TODO(b/179308296) Temporarily exclude Launcher from being given max bounds, by checking
- // if the caller is the recents component.
+ // TODO(b/179308296) Temporarily - never report max bounds to only Launcher if the feature
+ // is disabled.
return config != null && !config.windowConfiguration.getMaxBounds().isEmpty()
- && !isRecentsComponent();
+ && (mDisplayInfo.shouldConstrainMetricsForLauncher || !isRecentsComponent());
}
/**
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 8e5f905..6572510 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -306,6 +306,13 @@
public float brightnessDefault;
/**
+ * @hide
+ * True if Display#getRealSize and getRealMetrics should be constrained for Launcher, false
+ * otherwise.
+ */
+ public boolean shouldConstrainMetricsForLauncher = false;
+
+ /**
* The {@link RoundedCorners} if present, otherwise {@code null}.
*/
@Nullable
@@ -381,7 +388,8 @@
&& brightnessMinimum == other.brightnessMinimum
&& brightnessMaximum == other.brightnessMaximum
&& brightnessDefault == other.brightnessDefault
- && Objects.equals(roundedCorners, other.roundedCorners);
+ && Objects.equals(roundedCorners, other.roundedCorners)
+ && shouldConstrainMetricsForLauncher == other.shouldConstrainMetricsForLauncher;
}
@Override
@@ -432,6 +440,7 @@
brightnessMaximum = other.brightnessMaximum;
brightnessDefault = other.brightnessDefault;
roundedCorners = other.roundedCorners;
+ shouldConstrainMetricsForLauncher = other.shouldConstrainMetricsForLauncher;
}
public void readFromParcel(Parcel source) {
@@ -488,6 +497,7 @@
for (int i = 0; i < numUserDisabledFormats; i++) {
userDisabledHdrTypes[i] = source.readInt();
}
+ shouldConstrainMetricsForLauncher = source.readBoolean();
}
@Override
@@ -542,6 +552,7 @@
for (int i = 0; i < userDisabledHdrTypes.length; i++) {
dest.writeInt(userDisabledHdrTypes[i]);
}
+ dest.writeBoolean(shouldConstrainMetricsForLauncher);
}
@Override
@@ -796,6 +807,8 @@
sb.append(brightnessMaximum);
sb.append(", brightnessDefault ");
sb.append(brightnessDefault);
+ sb.append(", shouldConstrainMetricsForLauncher ");
+ sb.append(shouldConstrainMetricsForLauncher);
sb.append("}");
return sb.toString();
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 48ef27f..a4e7a43 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -33,6 +33,7 @@
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.RenderNode;
@@ -237,15 +238,6 @@
new SurfaceControl.Transaction();
/**
- * Transaction that should be used for
- * {@link RenderNode.PositionUpdateListener#positionChanged(long, int, int, int, int)}
- * The callback is invoked from a thread pool so it's not thread safe with other render thread
- * transactions. Keep the transactions for position changed callbacks on its own transaction.
- */
- private final SurfaceControl.Transaction mPositionChangedTransaction =
- new SurfaceControl.Transaction();
-
- /**
* A temporary transaction holder that should only be used when applying right away. There
* should be no assumption about thread safety for this transaction.
*/
@@ -295,7 +287,6 @@
int defStyleRes, boolean disableBackgroundLayer) {
super(context, attrs, defStyleAttr, defStyleRes);
mUseBlastAdapter = useBlastAdapter(context);
- mRenderNode.addPositionUpdateListener(mPositionListener);
setWillNotDraw(true);
mDisableBackgroundLayer = disableBackgroundLayer;
@@ -943,6 +934,24 @@
}
}
+
+ // The position update listener is used to safely share the surface size between render thread
+ // workers and the UI thread. Both threads need to know the surface size to determine the scale.
+ // The parent layer scales the surface size to view size. The child (BBQ) layer scales
+ // the buffer to the surface size. Both scales along with the window crop must be applied
+ // synchronously otherwise we may see flickers.
+ // When the listener is updated, we will get at least a single position update call so we can
+ // guarantee any changes we post will be applied.
+ private void replacePositionUpdateListener(int surfaceWidth, int surfaceHeight,
+ @Nullable Transaction geometryTransaction) {
+ if (mPositionListener != null) {
+ mRenderNode.removePositionUpdateListener(mPositionListener);
+ }
+ mPositionListener = new SurfaceViewPositionUpdateListener(surfaceWidth, surfaceHeight,
+ geometryTransaction);
+ mRenderNode.addPositionUpdateListener(mPositionListener);
+ }
+
private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
boolean creating, boolean sizeChanged, boolean hintChanged) {
boolean realSizeChanged = false;
@@ -985,13 +994,13 @@
// While creating the surface, we will set it's initial
// geometry. Outside of that though, we should generally
// leave it to the RenderThread.
- //
- // There is one more case when the buffer size changes we aren't yet
- // prepared to sync (as even following the transaction applying
- // we still need to latch a buffer).
- // b/28866173
- if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
- onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
+ Transaction geometryTransaction = new Transaction();
+ geometryTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
+ if ((sizeChanged || hintChanged) && !creating) {
+ setBufferSize(geometryTransaction);
+ }
+ if (sizeChanged || creating || !isHardwareAccelerated()) {
+ onSetSurfacePositionAndScaleRT(geometryTransaction, mSurfaceControl,
mScreenRect.left, /*positionLeft*/
mScreenRect.top /*positionTop*/ ,
mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
@@ -1002,17 +1011,31 @@
// use SCALING_MODE_SCALE and submit a larger size than the surface
// size.
if (mClipSurfaceToBounds && mClipBounds != null) {
- mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
+ geometryTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
} else {
- mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
+ geometryTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
mSurfaceHeight);
}
- }
- mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
- if ((sizeChanged || hintChanged) && !creating) {
- setBufferSize(mTmpTransaction);
- }
+ boolean applyChangesOnRenderThread =
+ sizeChanged && !creating && isHardwareAccelerated();
+ if (isHardwareAccelerated()) {
+ // This will consume the passed in transaction and the transaction will be
+ // applied on a render worker thread.
+ replacePositionUpdateListener(mSurfaceWidth, mSurfaceHeight,
+ applyChangesOnRenderThread ? geometryTransaction : null);
+ }
+ if (DEBUG_POSITION) {
+ Log.d(TAG, String.format(
+ "%d updateSurfacePosition %s"
+ + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
+ System.identityHashCode(this),
+ applyChangesOnRenderThread ? "RenderWorker" : "UiThread",
+ mScreenRect.left, mScreenRect.top, mScreenRect.right,
+ mScreenRect.bottom, mSurfaceWidth, mSurfaceHeight));
+ }
+ }
+ mTmpTransaction.merge(geometryTransaction);
mTmpTransaction.apply();
updateEmbeddedAccessibilityMatrix();
@@ -1399,19 +1422,6 @@
mTmpTransaction.apply();
}
- private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
- Rect position) {
- onSetSurfacePositionAndScaleRT(t, surface,
- position.left /*positionLeft*/,
- position.top /*positionTop*/,
- position.width() / (float) mSurfaceWidth /*postScaleX*/,
- position.height() / (float) mSurfaceHeight /*postScaleY*/);
-
- if (mViewVisibility) {
- t.show(surface);
- }
- }
-
/**
* @return The last render position of the backing surface or an empty rect.
*
@@ -1421,13 +1431,6 @@
return mRTLastReportedPosition;
}
- private void setParentSpaceRectangle(Rect position, long frameNumber, Transaction t) {
- final ViewRootImpl viewRoot = getViewRootImpl();
- applySurfaceTransforms(mSurfaceControl, t, position);
- applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber);
- applyOrMergeTransaction(t, frameNumber);
- }
-
private void applyOrMergeTransaction(Transaction t, long frameNumber) {
final ViewRootImpl viewRoot = getViewRootImpl();
boolean useBLAST = viewRoot != null && useBLASTSync(viewRoot);
@@ -1440,9 +1443,24 @@
}
private Rect mRTLastReportedPosition = new Rect();
+ private Point mRTLastReportedSurfaceSize = new Point();
- private RenderNode.PositionUpdateListener mPositionListener =
- new RenderNode.PositionUpdateListener() {
+ private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
+ int mRtSurfaceWidth = -1;
+ int mRtSurfaceHeight = -1;
+ private final SurfaceControl.Transaction mPositionChangedTransaction =
+ new SurfaceControl.Transaction();
+ boolean mPendingTransaction = false;
+
+ SurfaceViewPositionUpdateListener(int surfaceWidth, int surfaceHeight,
+ @Nullable Transaction t) {
+ mRtSurfaceWidth = surfaceWidth;
+ mRtSurfaceHeight = surfaceHeight;
+ if (t != null) {
+ mPositionChangedTransaction.merge(t);
+ mPendingTransaction = true;
+ }
+ }
@Override
public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
@@ -1464,21 +1482,34 @@
if (mRTLastReportedPosition.left == left
&& mRTLastReportedPosition.top == top
&& mRTLastReportedPosition.right == right
- && mRTLastReportedPosition.bottom == bottom) {
+ && mRTLastReportedPosition.bottom == bottom
+ && mRTLastReportedSurfaceSize.x == mRtSurfaceWidth
+ && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight
+ && !mPendingTransaction) {
return;
}
try {
if (DEBUG_POSITION) {
Log.d(TAG, String.format(
"%d updateSurfacePosition RenderWorker, frameNr = %d, "
- + "position = [%d, %d, %d, %d]",
- System.identityHashCode(this), frameNumber,
- left, top, right, bottom));
+ + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
+ System.identityHashCode(SurfaceView.this), frameNumber,
+ left, top, right, bottom, mRtSurfaceWidth, mRtSurfaceHeight));
}
mRTLastReportedPosition.set(left, top, right, bottom);
- setParentSpaceRectangle(mRTLastReportedPosition, frameNumber,
- mPositionChangedTransaction);
- // Now overwrite mRTLastReportedPosition with our values
+ mRTLastReportedSurfaceSize.set(mRtSurfaceWidth, mRtSurfaceHeight);
+ onSetSurfacePositionAndScaleRT(mPositionChangedTransaction, mSurfaceControl,
+ mRTLastReportedPosition.left /*positionLeft*/,
+ mRTLastReportedPosition.top /*positionTop*/,
+ mRTLastReportedPosition.width() / (float) mRtSurfaceWidth /*postScaleX*/,
+ mRTLastReportedPosition.height() / (float) mRtSurfaceHeight /*postScaleY*/);
+ if (mViewVisibility) {
+ mPositionChangedTransaction.show(mSurfaceControl);
+ }
+ applyChildSurfaceTransaction_renderWorker(mPositionChangedTransaction,
+ getViewRootImpl().mSurface, frameNumber);
+ applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
+ mPendingTransaction = false;
} catch (Exception ex) {
Log.e(TAG, "Exception from repositionChild", ex);
}
@@ -1502,7 +1533,13 @@
System.identityHashCode(this), frameNumber));
}
mRTLastReportedPosition.setEmpty();
-
+ mRTLastReportedSurfaceSize.set(-1, -1);
+ if (mPendingTransaction) {
+ Log.w(TAG, System.identityHashCode(SurfaceView.this)
+ + "Pending transaction cleared.");
+ mPositionChangedTransaction.clear();
+ mPendingTransaction = false;
+ }
if (mSurfaceControl == null) {
return;
}
@@ -1521,7 +1558,9 @@
mRtHandlingPositionUpdates = false;
}
}
- };
+ }
+
+ private SurfaceViewPositionUpdateListener mPositionListener = null;
private SurfaceHolder.Callback[] getSurfaceCallbacks() {
SurfaceHolder.Callback[] callbacks;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f3ebe5b..ffc98d2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -19816,6 +19816,9 @@
/**
* Check if this view can be scrolled horizontally in a certain direction.
*
+ * <p>This is without regard to whether the view is enabled or not, or if it will scroll
+ * in response to user input or not.
+ *
* @param direction Negative to check scrolling left, positive to check scrolling right.
* @return true if this view can be scrolled in the specified direction, false otherwise.
*/
@@ -19833,6 +19836,9 @@
/**
* Check if this view can be scrolled vertically in a certain direction.
*
+ * <p>This is without regard to whether the view is enabled or not, or if it will scroll
+ * in response to user input or not.
+ *
* @param direction Negative to check scrolling up, positive to check scrolling down.
* @return true if this view can be scrolled in the specified direction, false otherwise.
*/
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 5f036a3..5185dc2 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -843,9 +843,14 @@
/**
* Called back when the connected IME switches between fullscreen and normal modes.
*
- * <p>Note: On {@link android.os.Build.VERSION_CODES#O} and later devices, input methods are no
- * longer allowed to directly call this method at any time. To signal this event in the target
- * application, input methods should always call
+ * <p><p><strong>Editor authors:</strong> There is a bug on
+ * {@link android.os.Build.VERSION_CODES#O} and later devices that this method is called back
+ * on the main thread even when {@link #getHandler()} is overridden. This bug is fixed in
+ * {@link android.os.Build.VERSION_CODES#TIRAMISU}.</p>
+ *
+ * <p><p><strong>IME authors:</strong> On {@link android.os.Build.VERSION_CODES#O} and later
+ * devices, input methods are no longer allowed to directly call this method at any time.
+ * To signal this event in the target application, input methods should always call
* {@link InputMethodService#updateFullscreenMode()} instead. This approach should work on API
* {@link android.os.Build.VERSION_CODES#N_MR1} and prior devices.</p>
*
@@ -927,14 +932,20 @@
boolean requestCursorUpdates(int cursorUpdateMode);
/**
- * Called by the {@link InputMethodManager} to enable application developers to specify a
- * dedicated {@link Handler} on which incoming IPC method calls from input methods will be
- * dispatched.
+ * Called by the system to enable application developers to specify a dedicated thread on which
+ * {@link InputConnection} methods are called back.
*
- * <p>Note: This does nothing when called from input methods.</p>
+ * <p><strong>Editor authors</strong>: although you can return your custom subclasses of
+ * {@link Handler}, the system only uses {@link android.os.Looper} returned from
+ * {@link Handler#getLooper()}. You cannot intercept or cancel {@link InputConnection}
+ * callbacks by implementing this method.</p>
+ *
+ * <p><strong>IME authors</strong>: This method is not intended to be called from the IME. You
+ * will always receive {@code null}.</p>
*
* @return {@code null} to use the default {@link Handler}.
*/
+ @Nullable
Handler getHandler();
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index c023c6e..ab7e5a9 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -950,15 +950,15 @@
}
case MSG_REPORT_FULLSCREEN_MODE: {
final boolean fullscreen = msg.arg1 != 0;
- InputConnection ic = null;
+ RemoteInputConnectionImpl ic = null;
synchronized (mH) {
if (mFullscreenMode != fullscreen && mServedInputConnection != null) {
- ic = mServedInputConnection.getInputConnection();
+ ic = mServedInputConnection;
mFullscreenMode = fullscreen;
}
}
if (ic != null) {
- ic.reportFullscreenMode(fullscreen);
+ ic.dispatchReportFullscreenMode(fullscreen);
}
return;
}
@@ -1381,8 +1381,7 @@
public boolean isAcceptingText() {
checkFocus();
synchronized (mH) {
- return mServedInputConnection != null
- && mServedInputConnection.getInputConnection() != null;
+ return mServedInputConnection != null && !mServedInputConnection.isFinished();
}
}
diff --git a/core/java/android/view/translation/Translator.java b/core/java/android/view/translation/Translator.java
index edd0d16..606f39d 100644
--- a/core/java/android/view/translation/Translator.java
+++ b/core/java/android/view/translation/Translator.java
@@ -18,6 +18,7 @@
import static android.view.translation.TranslationManager.STATUS_SYNC_CALL_FAIL;
import static android.view.translation.TranslationManager.SYNC_CALLS_TIMEOUT_MS;
+import static android.view.translation.UiTranslationController.DEBUG;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
@@ -38,7 +39,6 @@
import com.android.internal.os.IResultReceiver;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -395,27 +395,26 @@
private static class TranslationResponseCallbackImpl extends ITranslationCallback.Stub {
- private final WeakReference<Consumer<TranslationResponse>> mCallback;
- private final WeakReference<Executor> mExecutor;
+ private final Consumer<TranslationResponse> mCallback;
+ private final Executor mExecutor;
TranslationResponseCallbackImpl(Consumer<TranslationResponse> callback, Executor executor) {
- mCallback = new WeakReference<>(callback);
- mExecutor = new WeakReference<>(executor);
+ mCallback = callback;
+ mExecutor = executor;
}
@Override
public void onTranslationResponse(TranslationResponse response) throws RemoteException {
- final Consumer<TranslationResponse> callback = mCallback.get();
+ if (DEBUG) {
+ Log.i(TAG, "onTranslationResponse called.");
+ }
final Runnable runnable =
- () -> callback.accept(response);
- if (callback != null) {
- final Executor executor = mExecutor.get();
- final long token = Binder.clearCallingIdentity();
- try {
- executor.execute(runnable);
- } finally {
- restoreCallingIdentity(token);
- }
+ () -> mCallback.accept(response);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(runnable);
+ } finally {
+ restoreCallingIdentity(token);
}
}
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 91fc5a5..e827f0a 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -5824,25 +5824,6 @@
return false;
}
- /** @hide */
- public void updateAppInfo(@NonNull ApplicationInfo info) {
- if (mApplication != null && mApplication.sourceDir.equals(info.sourceDir)) {
- // Overlay paths are generated against a particular version of an application.
- // The overlays paths of a newly upgraded application are incompatible with the
- // old version of the application.
- mApplication = info;
- }
- if (hasSizedRemoteViews()) {
- for (RemoteViews layout : mSizedRemoteViews) {
- layout.updateAppInfo(info);
- }
- }
- if (hasLandscapeAndPortraitLayouts()) {
- mLandscape.updateAppInfo(info);
- mPortrait.updateAppInfo(info);
- }
- }
-
private Context getContextForResources(Context context) {
if (mApplication != null) {
if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index b7de7b8..1c5b39e 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -23,6 +23,7 @@
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
@@ -94,8 +95,16 @@
/** The container can show on top of lock screen. */
public static final int FLAG_OCCLUDES_KEYGUARD = 1 << 6;
+ /**
+ * Only for IS_DISPLAY containers. Is set if the display has system alert windows. This is
+ * used to prevent seamless rotation.
+ * TODO(b/194540864): Once we can include all windows in transition, then replace this with
+ * something like FLAG_IS_SYSTEM_ALERT instead. Then we can do mixed rotations.
+ */
+ public static final int FLAG_DISPLAY_HAS_ALERT_WINDOWS = 1 << 7;
+
/** The first unused bit. This can be used by remotes to attach custom flags to this change. */
- public static final int FLAG_FIRST_CUSTOM = 1 << 7;
+ public static final int FLAG_FIRST_CUSTOM = 1 << 8;
/** @hide */
@IntDef(prefix = { "FLAG_" }, value = {
@@ -107,6 +116,7 @@
FLAG_IS_VOICE_INTERACTION,
FLAG_IS_DISPLAY,
FLAG_OCCLUDES_KEYGUARD,
+ FLAG_DISPLAY_HAS_ALERT_WINDOWS,
FLAG_FIRST_CUSTOM
})
public @interface ChangeFlags {}
@@ -209,6 +219,10 @@
return mOptions;
}
+ /**
+ * @return the list of {@link Change}s in this transition. The list is sorted top-to-bottom
+ * in Z (meaning index 0 is the top-most container).
+ */
@NonNull
public List<Change> getChanges() {
return mChanges;
@@ -290,6 +304,9 @@
if ((flags & FLAG_OCCLUDES_KEYGUARD) != 0) {
sb.append((sb.length() == 0 ? "" : "|") + "OCCLUDES_KEYGUARD");
}
+ if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) {
+ sb.append((sb.length() == 0 ? "" : "|") + "DISPLAY_HAS_ALERT_WINDOWS");
+ }
if ((flags & FLAG_FIRST_CUSTOM) != 0) {
sb.append((sb.length() == 0 ? "" : "|") + "FIRST_CUSTOM");
}
@@ -337,6 +354,7 @@
private ActivityManager.RunningTaskInfo mTaskInfo = null;
private int mStartRotation = ROTATION_UNDEFINED;
private int mEndRotation = ROTATION_UNDEFINED;
+ private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
mContainer = container;
@@ -356,6 +374,7 @@
mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
mStartRotation = in.readInt();
mEndRotation = in.readInt();
+ mRotationAnimation = in.readInt();
}
/** Sets the parent of this change's container. The parent must be a participant or null. */
@@ -402,6 +421,14 @@
mEndRotation = end;
}
+ /**
+ * Sets the app-requested animation type for rotation. Will be one of the
+ * ROTATION_ANIMATION_ values in {@link android.view.WindowManager.LayoutParams};
+ */
+ public void setRotationAnimation(int anim) {
+ mRotationAnimation = anim;
+ }
+
/** @return the container that is changing. May be null if non-remotable (eg. activity) */
@Nullable
public WindowContainerToken getContainer() {
@@ -473,6 +500,11 @@
return mEndRotation;
}
+ /** @return the rotation animation. */
+ public int getRotationAnimation() {
+ return mRotationAnimation;
+ }
+
/** @hide */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -487,6 +519,7 @@
dest.writeTypedObject(mTaskInfo, flags);
dest.writeInt(mStartRotation);
dest.writeInt(mEndRotation);
+ dest.writeInt(mRotationAnimation);
}
@NonNull
@@ -514,7 +547,7 @@
return "{" + mContainer + "(" + mParent + ") leash=" + mLeash
+ " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb="
+ mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r="
- + mStartRotation + "->" + mEndRotation + "}";
+ + mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation + "}";
}
}
diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
index d1bca85..2d44054 100644
--- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
@@ -86,13 +86,17 @@
* @return {@link InputConnection} to which incoming IPCs will be dispatched.
*/
@Nullable
- public InputConnection getInputConnection() {
+ private InputConnection getInputConnection() {
synchronized (mLock) {
return mInputConnection;
}
}
- private boolean isFinished() {
+ /**
+ * @return {@code true} until the target {@link InputConnection} receives
+ * {@link InputConnection#closeConnection()} as a result of {@link #deactivate()}.
+ */
+ public boolean isFinished() {
synchronized (mLock) {
return mFinished;
}
@@ -169,6 +173,23 @@
}
}
+ /**
+ * Invoke {@link InputConnection#reportFullscreenMode(boolean)} or schedule it on the target
+ * thread associated with {@link InputConnection#getHandler()}.
+ *
+ * @param enabled the parameter to be passed to
+ * {@link InputConnection#reportFullscreenMode(boolean)}.
+ */
+ public void dispatchReportFullscreenMode(boolean enabled) {
+ dispatch(() -> {
+ final InputConnection ic = getInputConnection();
+ if (ic == null || !isActive()) {
+ return;
+ }
+ ic.reportFullscreenMode(enabled);
+ });
+ }
+
@Override
public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) {
dispatch(() -> {
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index a6d038d..8a1f1a0 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2432,6 +2432,12 @@
return (jint)nativeToJavaStatus(status);
}
+static jint android_media_AudioSystem_setHotwordDetectionServiceUid(JNIEnv *env, jobject thiz,
+ jint uid) {
+ status_t status = AudioSystem::setHotwordDetectionServiceUid(uid);
+ return (jint)nativeToJavaStatus(status);
+}
+
static jint
android_media_AudioSystem_setA11yServicesUids(JNIEnv *env, jobject thiz, jintArray uids) {
std::vector<uid_t> nativeUidsVector;
@@ -2804,6 +2810,8 @@
{"setSurroundFormatEnabled", "(IZ)I",
(void *)android_media_AudioSystem_setSurroundFormatEnabled},
{"setAssistantUid", "(I)I", (void *)android_media_AudioSystem_setAssistantUid},
+ {"setHotwordDetectionServiceUid", "(I)I",
+ (void *)android_media_AudioSystem_setHotwordDetectionServiceUid},
{"setA11yServicesUids", "([I)I", (void *)android_media_AudioSystem_setA11yServicesUids},
{"isHapticPlaybackSupported", "()Z",
(void *)android_media_AudioSystem_isHapticPlaybackSupported},
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 5245437..4b1c544 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1938,7 +1938,7 @@
<string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing-Warnung"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbeitsprofil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Gewarnt"</string>
- <string name="notification_verified_content_description" msgid="6401483602782359391">"Bestätigt"</string>
+ <string name="notification_verified_content_description" msgid="6401483602782359391">"Verifiziert"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Maximieren"</string>
<string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Minimieren"</string>
<string name="expand_action_accessibility" msgid="1947657036871746627">"Maximierung ein-/auschalten"</string>
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index 4925209..872331c 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -67,7 +67,7 @@
@NonNull RippleAnimationSession enter(Canvas canvas) {
mStartTime = AnimationUtils.currentAnimationTimeMillis();
- if (isHwAccelerated(canvas)) {
+ if (useRTAnimations(canvas)) {
enterHardware((RecordingCanvas) canvas);
} else {
enterSoftware();
@@ -82,7 +82,7 @@
}
@NonNull RippleAnimationSession exit(Canvas canvas) {
- if (isHwAccelerated(canvas)) exitHardware((RecordingCanvas) canvas);
+ if (useRTAnimations(canvas)) exitHardware((RecordingCanvas) canvas);
else exitSoftware();
return this;
}
@@ -102,8 +102,12 @@
return this;
}
- private boolean isHwAccelerated(Canvas canvas) {
- return canvas.isHardwareAccelerated() && !mForceSoftware;
+ private boolean useRTAnimations(Canvas canvas) {
+ if (mForceSoftware) return false;
+ if (!canvas.isHardwareAccelerated()) return false;
+ RecordingCanvas hwCanvas = (RecordingCanvas) canvas;
+ if (hwCanvas.mNode == null || !hwCanvas.mNode.isAttached()) return false;
+ return true;
}
private void exitSoftware() {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index d3cff5c..7354c90 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -49,7 +49,9 @@
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Build;
+import android.os.Looper;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
@@ -113,6 +115,7 @@
* @attr ref android.R.styleable#RippleDrawable_color
*/
public class RippleDrawable extends LayerDrawable {
+ private static final String TAG = "RippleDrawable";
/**
* Radius value that specifies the ripple radius should be computed based
* on the size of the ripple's container.
@@ -848,6 +851,10 @@
private void startBackgroundAnimation() {
mRunBackgroundAnimation = false;
+ if (Looper.myLooper() == null) {
+ Log.w(TAG, "Thread doesn't have a looper. Skipping animation.");
+ return;
+ }
mBackgroundAnimation = ValueAnimator.ofFloat(mBackgroundOpacity, mTargetBackgroundOpacity);
mBackgroundAnimation.setInterpolator(LINEAR_INTERPOLATOR);
mBackgroundAnimation.setDuration(BACKGROUND_OPACITY_DURATION);
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 624b8b3..c2b6ffb 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -31,7 +31,7 @@
<string name="accessibility_action_pip_stash" msgid="4060775037619702641">"స్టాచ్"</string>
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ఆన్స్టాచ్"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"స్క్రీన్ విభజనతో యాప్ పని చేయకపోవచ్చు."</string>
- <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"యాప్లో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ప్రత్యామ్నాయ డిస్ప్లేలో యాప్ పని చేయకపోవచ్చు."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ప్రత్యామ్నాయ డిస్ప్లేల్లో ప్రారంభానికి యాప్ మద్దతు లేదు."</string>
<string name="accessibility_divider" msgid="703810061635792791">"విభజన స్క్రీన్ విభాగిని"</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index d1fbf31..9bbede3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -24,6 +24,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
+import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.pip.phone.PipTouchHandler;
import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -47,6 +48,7 @@
private final Optional<AppPairsController> mAppPairsOptional;
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
private final FullscreenTaskListener mFullscreenTaskListener;
+ private final Optional<FreeformTaskListener> mFreeformTaskListenerOptional;
private final ShellExecutor mMainExecutor;
private final Transitions mTransitions;
private final StartingWindowController mStartingWindow;
@@ -62,6 +64,7 @@
Optional<AppPairsController> appPairsOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
+ Optional<Optional<FreeformTaskListener>> freeformTaskListenerOptional,
Transitions transitions,
StartingWindowController startingWindow,
ShellExecutor mainExecutor) {
@@ -74,6 +77,7 @@
mAppPairsOptional = appPairsOptional;
mFullscreenTaskListener = fullscreenTaskListener;
mPipTouchHandlerOptional = pipTouchHandlerOptional;
+ mFreeformTaskListenerOptional = freeformTaskListenerOptional.flatMap(f -> f);
mTransitions = transitions;
mMainExecutor = mainExecutor;
mStartingWindow = startingWindow;
@@ -108,6 +112,11 @@
// controller instead of the feature interface, can just initialize the touch handler if
// needed
mPipTouchHandlerOptional.ifPresent((handler) -> handler.init());
+
+ // Initialize optional freeform
+ mFreeformTaskListenerOptional.ifPresent(f ->
+ mShellTaskOrganizer.addListenerForType(
+ f, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM));
}
@ExternalThread
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index ba0ab6d..ab8a21c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -71,12 +71,14 @@
public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2;
public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3;
public static final int TASK_LISTENER_TYPE_PIP = -4;
+ public static final int TASK_LISTENER_TYPE_FREEFORM = -5;
@IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = {
TASK_LISTENER_TYPE_UNDEFINED,
TASK_LISTENER_TYPE_FULLSCREEN,
TASK_LISTENER_TYPE_MULTI_WINDOW,
TASK_LISTENER_TYPE_PIP,
+ TASK_LISTENER_TYPE_FREEFORM,
})
public @interface TaskListenerType {}
@@ -572,6 +574,7 @@
case WINDOWING_MODE_PINNED:
return TASK_LISTENER_TYPE_PIP;
case WINDOWING_MODE_FREEFORM:
+ return TASK_LISTENER_TYPE_FREEFORM;
case WINDOWING_MODE_UNDEFINED:
default:
return TASK_LISTENER_TYPE_UNDEFINED;
@@ -586,6 +589,8 @@
return "TASK_LISTENER_TYPE_MULTI_WINDOW";
case TASK_LISTENER_TYPE_PIP:
return "TASK_LISTENER_TYPE_PIP";
+ case TASK_LISTENER_TYPE_FREEFORM:
+ return "TASK_LISTENER_TYPE_FREEFORM";
case TASK_LISTENER_TYPE_UNDEFINED:
return "TASK_LISTENER_TYPE_UNDEFINED";
default:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index b7235a3..b90283f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -82,6 +82,9 @@
private boolean mHasNavigationBar = false;
private boolean mHasStatusBar = false;
private int mNavBarFrameHeight = 0;
+ private boolean mAllowSeamlessRotationDespiteNavBarMoving = false;
+ private boolean mNavigationBarCanMove = false;
+ private boolean mReverseDefaultRotation = false;
@Override
public boolean equals(Object o) {
@@ -98,6 +101,10 @@
&& Objects.equals(mStableInsets, other.mStableInsets)
&& mHasNavigationBar == other.mHasNavigationBar
&& mHasStatusBar == other.mHasStatusBar
+ && mAllowSeamlessRotationDespiteNavBarMoving
+ == other.mAllowSeamlessRotationDespiteNavBarMoving
+ && mNavigationBarCanMove == other.mNavigationBarCanMove
+ && mReverseDefaultRotation == other.mReverseDefaultRotation
&& mNavBarFrameHeight == other.mNavBarFrameHeight;
}
@@ -105,7 +112,8 @@
public int hashCode() {
return Objects.hash(mUiMode, mWidth, mHeight, mCutout, mRotation, mDensityDpi,
mNonDecorInsets, mStableInsets, mHasNavigationBar, mHasStatusBar,
- mNavBarFrameHeight);
+ mNavBarFrameHeight, mAllowSeamlessRotationDespiteNavBarMoving,
+ mNavigationBarCanMove, mReverseDefaultRotation);
}
/**
@@ -150,6 +158,9 @@
mDensityDpi = dl.mDensityDpi;
mHasNavigationBar = dl.mHasNavigationBar;
mHasStatusBar = dl.mHasStatusBar;
+ mAllowSeamlessRotationDespiteNavBarMoving = dl.mAllowSeamlessRotationDespiteNavBarMoving;
+ mNavigationBarCanMove = dl.mNavigationBarCanMove;
+ mReverseDefaultRotation = dl.mReverseDefaultRotation;
mNavBarFrameHeight = dl.mNavBarFrameHeight;
mNonDecorInsets.set(dl.mNonDecorInsets);
mStableInsets.set(dl.mStableInsets);
@@ -165,6 +176,10 @@
mDensityDpi = info.logicalDensityDpi;
mHasNavigationBar = hasNavigationBar;
mHasStatusBar = hasStatusBar;
+ mAllowSeamlessRotationDespiteNavBarMoving = res.getBoolean(
+ R.bool.config_allowSeamlessRotationDespiteNavBarMoving);
+ mNavigationBarCanMove = res.getBoolean(R.bool.config_navBarCanMove);
+ mReverseDefaultRotation = res.getBoolean(R.bool.config_reverseDefaultRotation);
recalcInsets(res);
}
@@ -249,6 +264,28 @@
return mNavBarFrameHeight;
}
+ /** @return whether we can seamlessly rotate even if nav-bar can change sides. */
+ public boolean allowSeamlessRotationDespiteNavBarMoving() {
+ return mAllowSeamlessRotationDespiteNavBarMoving;
+ }
+
+ /** @return whether the navigation bar will change sides during rotation. */
+ public boolean navigationBarCanMove() {
+ return mNavigationBarCanMove;
+ }
+
+ /** @return the rotation that would make the physical display "upside down". */
+ public int getUpsideDownRotation() {
+ boolean displayHardwareIsLandscape = mWidth > mHeight;
+ if ((mRotation % 2) != 0) {
+ displayHardwareIsLandscape = !displayHardwareIsLandscape;
+ }
+ if (displayHardwareIsLandscape) {
+ return mReverseDefaultRotation ? Surface.ROTATION_270 : Surface.ROTATION_90;
+ }
+ return Surface.ROTATION_180;
+ }
+
/** Gets the orientation of this layout */
public int getOrientation() {
return (mWidth > mHeight) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
new file mode 100644
index 0000000..5fb3297
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2021 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.wm.shell.freeform;
+
+import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.provider.Settings;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
+
+import java.io.PrintWriter;
+
+/**
+ * {@link ShellTaskOrganizer.TaskListener} for {@link
+ * ShellTaskOrganizer#TASK_LISTENER_TYPE_FREEFORM}.
+ */
+public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener {
+ private static final String TAG = "FreeformTaskListener";
+
+ private final SyncTransactionQueue mSyncQueue;
+
+ private final SparseArray<State> mTasks = new SparseArray<>();
+
+ private static class State {
+ RunningTaskInfo mTaskInfo;
+ SurfaceControl mLeash;
+ }
+
+ public FreeformTaskListener(SyncTransactionQueue syncQueue) {
+ mSyncQueue = syncQueue;
+ }
+
+ @Override
+ public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+ if (mTasks.get(taskInfo.taskId) != null) {
+ throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
+ taskInfo.taskId);
+ final State state = new State();
+ state.mTaskInfo = taskInfo;
+ state.mLeash = leash;
+ mTasks.put(taskInfo.taskId, state);
+
+ final Rect taskBounds = taskInfo.configuration.windowConfiguration.getBounds();
+ mSyncQueue.runInSync(t -> {
+ Point taskPosition = taskInfo.positionInParent;
+ t.setPosition(leash, taskPosition.x, taskPosition.y)
+ .setWindowCrop(leash, taskBounds.width(), taskBounds.height())
+ .show(leash);
+ });
+ }
+
+ @Override
+ public void onTaskVanished(RunningTaskInfo taskInfo) {
+ State state = mTasks.get(taskInfo.taskId);
+ if (state == null) {
+ Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+ return;
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
+ taskInfo.taskId);
+ mTasks.remove(taskInfo.taskId);
+ }
+
+ @Override
+ public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+ State state = mTasks.get(taskInfo.taskId);
+ if (state == null) {
+ throw new RuntimeException(
+ "Task info changed before appearing: #" + taskInfo.taskId);
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
+ taskInfo.taskId);
+ state.mTaskInfo = taskInfo;
+
+ final Rect taskBounds = taskInfo.configuration.windowConfiguration.getBounds();
+ final SurfaceControl leash = state.mLeash;
+ mSyncQueue.runInSync(t -> {
+ Point taskPosition = taskInfo.positionInParent;
+ t.setPosition(leash, taskPosition.x, taskPosition.y)
+ .setWindowCrop(leash, taskBounds.width(), taskBounds.height())
+ .show(leash);
+ });
+ }
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ pw.println(prefix + this);
+ pw.println(innerPrefix + mTasks.size() + " tasks");
+ }
+
+ @Override
+ public String toString() {
+ return TAG;
+ }
+
+ /**
+ * Checks if freeform support is enabled in system.
+ *
+ * @param context context used to check settings and package manager.
+ * @return {@code true} if freeform is enabled, {@code false} if not.
+ */
+ public static boolean isFreeformEnabled(Context context) {
+ return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
+ || Settings.Global.getInt(context.getContentResolver(),
+ DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
+ }
+
+ /**
+ * Creates {@link FreeformTaskListener} if freeform is enabled.
+ */
+ public static FreeformTaskListener create(Context context,
+ SyncTransactionQueue syncQueue) {
+ if (!isFreeformEnabled(context)) {
+ return null;
+ }
+
+ return new FreeformTaskListener(syncQueue);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index 21bc889..ff333c8c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -130,7 +130,7 @@
*/
public boolean getSettingsTapsAppToExit(ContentResolver resolver, int userId) {
return Settings.Secure.getIntForUser(resolver,
- Settings.Secure.TAPS_APP_TO_EXIT, 0, userId) == 1;
+ Settings.Secure.TAPS_APP_TO_EXIT, 1, userId) == 1;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 01134a7..b584038 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -23,6 +23,10 @@
import static android.app.ActivityOptions.ANIM_SCALE_UP;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
@@ -31,8 +35,10 @@
import static android.view.WindowManager.TRANSIT_RELAUNCH;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
+import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
@@ -68,9 +74,12 @@
import android.window.WindowContainerTransaction;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.AttributeCache;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -97,6 +106,7 @@
SystemProperties.getBoolean(DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY, true);
private final TransactionPool mTransactionPool;
+ private final DisplayController mDisplayController;
private final Context mContext;
private final ShellExecutor mMainExecutor;
private final ShellExecutor mAnimExecutor;
@@ -114,8 +124,10 @@
private ScreenRotationAnimation mRotationAnimation;
- DefaultTransitionHandler(@NonNull TransactionPool transactionPool, Context context,
+ DefaultTransitionHandler(@NonNull DisplayController displayController,
+ @NonNull TransactionPool transactionPool, Context context,
@NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
+ mDisplayController = displayController;
mTransactionPool = transactionPool;
mContext = context;
mMainExecutor = mainExecutor;
@@ -126,6 +138,110 @@
AttributeCache.init(context);
}
+ @VisibleForTesting
+ static boolean isRotationSeamless(@NonNull TransitionInfo info,
+ DisplayController displayController) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ "Display is rotating, check if it should be seamless.");
+ boolean checkedDisplayLayout = false;
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+
+ // Only look at changing things. showing/hiding don't need to rotate.
+ if (change.getMode() != TRANSIT_CHANGE) continue;
+
+ // This container isn't rotating, so we can ignore it.
+ if (change.getEndRotation() == change.getStartRotation()) continue;
+
+ if ((change.getFlags() & FLAG_IS_DISPLAY) != 0) {
+ // In the presence of System Alert windows we can not seamlessly rotate.
+ if ((change.getFlags() & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " display has system alert windows, so not seamless.");
+ return false;
+ }
+ } else if ((change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
+ if (change.getRotationAnimation() != ROTATION_ANIMATION_SEAMLESS) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " wallpaper is participating but isn't seamless.");
+ return false;
+ }
+ } else if (change.getTaskInfo() != null) {
+ // We only enable seamless rotation if all the visible task windows requested it.
+ if (change.getRotationAnimation() != ROTATION_ANIMATION_SEAMLESS) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " task %s isn't requesting seamless, so not seamless.",
+ change.getTaskInfo().taskId);
+ return false;
+ }
+
+ // This is the only way to get display-id currently, so we will check display
+ // capabilities here
+ if (!checkedDisplayLayout) {
+ // only need to check display once.
+ checkedDisplayLayout = true;
+ final DisplayLayout displayLayout = displayController.getDisplayLayout(
+ change.getTaskInfo().displayId);
+ // For the upside down rotation we don't rotate seamlessly as the navigation
+ // bar moves position. Note most apps (using orientation:sensor or user as
+ // opposed to fullSensor) will not enter the reverse portrait orientation, so
+ // actually the orientation won't change at all.
+ int upsideDownRotation = displayLayout.getUpsideDownRotation();
+ if (change.getStartRotation() == upsideDownRotation
+ || change.getEndRotation() == upsideDownRotation) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " rotation involves upside-down portrait, so not seamless.");
+ return false;
+ }
+
+ // If the navigation bar can't change sides, then it will jump when we change
+ // orientations and we don't rotate seamlessly - unless that is allowed, eg.
+ // with gesture navigation where the navbar is low-profile enough that this
+ // isn't very noticeable.
+ if (!displayLayout.allowSeamlessRotationDespiteNavBarMoving()
+ && (!(displayLayout.navigationBarCanMove()
+ && (change.getStartAbsBounds().width()
+ != change.getStartAbsBounds().height())))) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " nav bar changes sides, so not seamless.");
+ return false;
+ }
+ }
+ }
+ }
+
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Rotation IS seamless.");
+ return true;
+ }
+
+ /**
+ * Gets the rotation animation for the topmost task. Assumes that seamless is checked
+ * elsewhere, so it will default SEAMLESS to ROTATE.
+ */
+ private int getRotationAnimation(@NonNull TransitionInfo info) {
+ // Traverse in top-to-bottom order so that the first task is top-most
+ for (int i = 0; i < info.getChanges().size(); ++i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+
+ // Only look at changing things. showing/hiding don't need to rotate.
+ if (change.getMode() != TRANSIT_CHANGE) continue;
+
+ // This container isn't rotating, so we can ignore it.
+ if (change.getEndRotation() == change.getStartRotation()) continue;
+
+ if (change.getTaskInfo() != null) {
+ final int anim = change.getRotationAnimation();
+ if (anim == ROTATION_ANIMATION_UNSPECIFIED
+ // Fallback animation for seamless should also be default.
+ || anim == ROTATION_ANIMATION_SEAMLESS) {
+ return ROTATION_ANIMATION_ROTATE;
+ }
+ return anim;
+ }
+ }
+ return ROTATION_ANIMATION_ROTATE;
+ }
+
@Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@@ -168,11 +284,15 @@
if (info.getType() == TRANSIT_CHANGE && change.getMode() == TRANSIT_CHANGE
&& (change.getEndRotation() != change.getStartRotation())
&& (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
- mRotationAnimation = new ScreenRotationAnimation(mContext, mSurfaceSession,
- mTransactionPool, startTransaction, change, info.getRootLeash());
- mRotationAnimation.startAnimation(animations, onAnimFinish,
- mTransitionAnimationScaleSetting, mMainExecutor, mAnimExecutor);
- continue;
+ boolean isSeamless = isRotationSeamless(info, mDisplayController);
+ final int anim = getRotationAnimation(info);
+ if (!(isSeamless || anim == ROTATION_ANIMATION_JUMPCUT)) {
+ mRotationAnimation = new ScreenRotationAnimation(mContext, mSurfaceSession,
+ mTransactionPool, startTransaction, change, info.getRootLeash());
+ mRotationAnimation.startAnimation(animations, onAnimFinish,
+ mTransitionAnimationScaleSetting, mMainExecutor, mAnimExecutor);
+ continue;
+ }
}
if (change.getMode() == TRANSIT_CHANGE) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 01ef2a6..09dfabf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -54,6 +54,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
@@ -113,15 +114,16 @@
private final ArrayList<ActiveTransition> mActiveTransitions = new ArrayList<>();
public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
- @NonNull Context context, @NonNull ShellExecutor mainExecutor,
- @NonNull ShellExecutor animExecutor) {
+ @NonNull DisplayController displayController, @NonNull Context context,
+ @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
mOrganizer = organizer;
mContext = context;
mMainExecutor = mainExecutor;
mAnimExecutor = animExecutor;
mPlayerImpl = new TransitionPlayerImpl();
// The very last handler (0 in the list) should be the default one.
- mHandlers.add(new DefaultTransitionHandler(pool, context, mainExecutor, animExecutor));
+ mHandlers.add(new DefaultTransitionHandler(displayController, pool, context, mainExecutor,
+ animExecutor));
// Next lowest priority is remote transitions.
mRemoteTransitionHandler = new RemoteTransitionHandler(mainExecutor);
mHandlers.add(mRemoteTransitionHandler);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 21329c7..84565e5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -20,12 +20,18 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -49,6 +55,9 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.view.IDisplayWindowListener;
+import android.view.IWindowManager;
+import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.IRemoteTransition;
@@ -66,12 +75,15 @@
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.wm.shell.TestShellExecutor;
+import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.util.ArrayList;
@@ -98,8 +110,7 @@
@Test
public void testBasicTransitionFlow() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
IBinder transitToken = new Binder();
@@ -118,8 +129,7 @@
@Test
public void testNonDefaultHandler() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
final WindowContainerTransaction handlerWCT = new WindowContainerTransaction();
@@ -202,8 +212,7 @@
@Test
public void testRequestRemoteTransition() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
final boolean[] remoteCalled = new boolean[]{false};
@@ -297,8 +306,7 @@
@Test
public void testRegisteredRemoteTransition() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
final boolean[] remoteCalled = new boolean[]{false};
@@ -343,8 +351,7 @@
@Test
public void testOneShotRemoteHandler() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
final boolean[] remoteCalled = new boolean[]{false};
@@ -390,8 +397,7 @@
@Test
public void testTransitionQueueing() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
IBinder transitToken1 = new Binder();
@@ -431,8 +437,7 @@
@Test
public void testTransitionMerging() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
mDefaultHandler.setSimulateMerge(true);
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
@@ -468,6 +473,63 @@
assertEquals(0, mDefaultHandler.activeCount());
}
+ @Test
+ public void testShouldRotateSeamlessly() throws Exception {
+ final RunningTaskInfo taskInfo =
+ createTaskInfo(1, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final RunningTaskInfo taskInfoPip =
+ createTaskInfo(1, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
+
+ final DisplayController displays = createTestDisplayController();
+ final @Surface.Rotation int upsideDown = displays
+ .getDisplayLayout(DEFAULT_DISPLAY).getUpsideDownRotation();
+
+ final TransitionInfo normalDispRotate = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+ .build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo).setRotate().build())
+ .build();
+ assertFalse(DefaultTransitionHandler.isRotationSeamless(normalDispRotate, displays));
+
+ // Seamless if all tasks are seamless
+ final TransitionInfo rotateSeamless = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+ .build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+ .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+ .build();
+ assertTrue(DefaultTransitionHandler.isRotationSeamless(rotateSeamless, displays));
+
+ // Not seamless if there is PiP (or any other non-seamless task)
+ final TransitionInfo pipDispRotate = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+ .build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+ .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfoPip)
+ .setRotate().build())
+ .build();
+ assertFalse(DefaultTransitionHandler.isRotationSeamless(pipDispRotate, displays));
+
+ // Not seamless if one of rotations is upside-down
+ final TransitionInfo seamlessUpsideDown = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY)
+ .setRotate(upsideDown, ROTATION_ANIMATION_UNSPECIFIED).build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+ .setRotate(upsideDown, ROTATION_ANIMATION_SEAMLESS).build())
+ .build();
+ assertFalse(DefaultTransitionHandler.isRotationSeamless(seamlessUpsideDown, displays));
+
+ // Not seamless if system alert windows
+ final TransitionInfo seamlessButAlert = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(
+ FLAG_IS_DISPLAY | FLAG_DISPLAY_HAS_ALERT_WINDOWS).setRotate().build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+ .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+ .build();
+ assertFalse(DefaultTransitionHandler.isRotationSeamless(seamlessButAlert, displays));
+ }
+
class TransitionInfoBuilder {
final TransitionInfo mInfo;
@@ -490,11 +552,53 @@
return addChange(mode, null /* taskInfo */);
}
+ TransitionInfoBuilder addChange(TransitionInfo.Change change) {
+ mInfo.addChange(change);
+ return this;
+ }
+
TransitionInfo build() {
return mInfo;
}
}
+ class ChangeBuilder {
+ final TransitionInfo.Change mChange;
+
+ ChangeBuilder(@WindowManager.TransitionType int mode) {
+ mChange = new TransitionInfo.Change(null /* token */, null /* leash */);
+ mChange.setMode(mode);
+ }
+
+ ChangeBuilder setFlags(@TransitionInfo.ChangeFlags int flags) {
+ mChange.setFlags(flags);
+ return this;
+ }
+
+ ChangeBuilder setTask(RunningTaskInfo taskInfo) {
+ mChange.setTaskInfo(taskInfo);
+ return this;
+ }
+
+ ChangeBuilder setRotate(int anim) {
+ return setRotate(Surface.ROTATION_90, anim);
+ }
+
+ ChangeBuilder setRotate() {
+ return setRotate(ROTATION_ANIMATION_UNSPECIFIED);
+ }
+
+ ChangeBuilder setRotate(@Surface.Rotation int target, int anim) {
+ mChange.setRotation(Surface.ROTATION_0, target);
+ mChange.setRotationAnimation(anim);
+ return this;
+ }
+
+ TransitionInfo.Change build() {
+ return mChange;
+ }
+ }
+
class TestTransitionHandler implements Transitions.TransitionHandler {
ArrayList<Transitions.TransitionFinishCallback> mFinishes = new ArrayList<>();
final ArrayList<IBinder> mMerged = new ArrayList<>();
@@ -566,4 +670,45 @@
return taskInfo;
}
+ private DisplayController createTestDisplayController() {
+ IWindowManager mockWM = mock(IWindowManager.class);
+ final IDisplayWindowListener[] displayListener = new IDisplayWindowListener[1];
+ try {
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ displayListener[0] = invocation.getArgument(0);
+ return null;
+ }
+ }).when(mockWM).registerDisplayWindowListener(any());
+ } catch (RemoteException e) {
+ // No remote stuff happening, so this can't be hit
+ }
+ DisplayController out = new DisplayController(mContext, mockWM, mMainExecutor);
+ try {
+ displayListener[0].onDisplayAdded(DEFAULT_DISPLAY);
+ mMainExecutor.flushAll();
+ } catch (RemoteException e) {
+ // Again, no remote stuff
+ }
+ return out;
+ }
+
+ private Transitions createTestTransitions() {
+ return new Transitions(mOrganizer, mTransactionPool, createTestDisplayController(),
+ mContext, mMainExecutor, mAnimExecutor);
+ }
+//
+// private class TestDisplayController extends DisplayController {
+// private final DisplayLayout mTestDisplayLayout;
+// TestDisplayController() {
+// super(mContext, mock(IWindowManager.class), mMainExecutor);
+// mTestDisplayLayout = new DisplayLayout();
+// mTestDisplayLayout.
+// }
+//
+// @Override
+// DisplayLayout
+// }
+
}
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index c827932..cb887f2 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -38,6 +38,17 @@
public abstract void updateRingerModeAffectedStreamsInternal();
+ /**
+ * Notify the UID of the currently active {@link android.service.voice.HotwordDetectionService}.
+ *
+ * <p>The caller is expected to take care of any performance implications, e.g. by using a
+ * background thread to call this method.</p>
+ *
+ * @param uid UID of the currently active service or {@link android.os.Process#INVALID_UID} if
+ * none.
+ */
+ public abstract void setHotwordDetectionServiceUid(int uid);
+
public abstract void setAccessibilityServiceUids(IntArray uids);
/**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 321db4e..5bd6891 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1769,6 +1769,13 @@
public static native int setAssistantUid(int uid);
/**
+ * Communicate UID of the current {@link android.service.voice.HotwordDetectionService} to audio
+ * policy service.
+ * @hide
+ */
+ public static native int setHotwordDetectionServiceUid(int uid);
+
+ /**
* @hide
* Communicate UIDs of active accessibility services to audio policy service.
*/
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 3b0f577..7c750ce 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -39,8 +39,8 @@
ISession createSession(String packageName, in ISessionCallback sessionCb, String tag,
in Bundle sessionInfo, int userId);
List<MediaSession.Token> getSessions(in ComponentName compName, int userId);
- MediaSession.Token getMediaKeyEventSession();
- String getMediaKeyEventSessionPackageName();
+ MediaSession.Token getMediaKeyEventSession(in ComponentName compName);
+ String getMediaKeyEventSessionPackageName(in ComponentName compName);
void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
boolean needWakeLock);
boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
@@ -66,7 +66,8 @@
void addOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
void removeOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
void addOnMediaKeyEventSessionChangedListener(
- in IOnMediaKeyEventSessionChangedListener listener);
+ in IOnMediaKeyEventSessionChangedListener listener,
+ in ComponentName notificationListener);
void removeOnMediaKeyEventSessionChangedListener(
in IOnMediaKeyEventSessionChangedListener listener);
void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 269b70b..8e731a5 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -205,7 +205,28 @@
@Nullable
public MediaSession.Token getMediaKeyEventSession() {
try {
- return mService.getMediaKeyEventSession();
+ return mService.getMediaKeyEventSession(null);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Failed to get media key event session", ex);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the media key event session, which would receive a media key event unless specified.
+ * <p>
+ * This requires that your app is an enabled notificationlistener using the
+ * {@link NotificationListenerService} APIs, in which case you must pass
+ * the {@link ComponentName} of your enabled listener.
+ *
+ * @return The media key event session, which would receive key events by default, unless
+ * the caller has specified the target. Can be {@code null}.
+ */
+ @Nullable
+ public MediaSession.Token getMediaKeyEventSession(@NonNull ComponentName notificationListener) {
+ Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
+ try {
+ return mService.getMediaKeyEventSession(notificationListener);
} catch (RemoteException ex) {
Log.e(TAG, "Failed to get media key event session", ex);
}
@@ -224,10 +245,34 @@
@NonNull
public String getMediaKeyEventSessionPackageName() {
try {
- String packageName = mService.getMediaKeyEventSessionPackageName();
+ String packageName = mService.getMediaKeyEventSessionPackageName(null);
return (packageName != null) ? packageName : "";
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to get media key event session", ex);
+ Log.e(TAG, "Failed to get media key event session package name", ex);
+ }
+ return "";
+ }
+
+ /**
+ * Gets the package name of the media key event session.
+ * <p>
+ * This requires that your app is an enabled notificationlistener using the
+ * {@link NotificationListenerService} APIs, in which case you must pass
+ * the {@link ComponentName} of your enabled listener.
+ *
+ * @return The package name of the media key event session or the last session's media button
+ * receiver if the media key event session is {@code null}. Returns an empty string
+ * if neither of them exists.
+ * @see #getMediaKeyEventSession(ComponentName)
+ */
+ @NonNull
+ public String getMediaKeyEventSessionPackageName(@NonNull ComponentName notificationListener) {
+ Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
+ try {
+ String packageName = mService.getMediaKeyEventSessionPackageName(notificationListener);
+ return (packageName != null) ? packageName : "";
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Failed to get media key event session package name", ex);
}
return "";
}
@@ -905,44 +950,67 @@
public void addOnMediaKeyEventSessionChangedListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull OnMediaKeyEventSessionChangedListener listener) {
+ addOnMediaKeyEventSessionChangedListenerInternal(null, executor, listener);
+ }
+
+ /**
+ * Add a listener to be notified when the media key session is changed.
+ * <p>
+ * This requires that your app is an enabled notificationlistener using the
+ * {@link NotificationListenerService} APIs, in which case you must pass
+ * the {@link ComponentName} of your enabled listener.
+ *
+ * @param notificationListener The enabled notification listener component.
+ * @param executor The executor on which the listener should be invoked.
+ * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
+ */
+ public void addOnMediaKeyEventSessionChangedListener(
+ @NonNull ComponentName notificationListener,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnMediaKeyEventSessionChangedListener listener) {
+ Objects.requireNonNull(notificationListener, "notificationListener shouldn't be null");
+ addOnMediaKeyEventSessionChangedListenerInternal(notificationListener, executor, listener);
+ }
+
+ private void addOnMediaKeyEventSessionChangedListenerInternal(
+ @Nullable ComponentName notificationListener,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnMediaKeyEventSessionChangedListener listener) {
Objects.requireNonNull(executor, "executor shouldn't be null");
Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
try {
+ if (mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
+ mService.addOnMediaKeyEventSessionChangedListener(
+ mOnMediaKeyEventSessionChangedListenerStub, notificationListener);
+ }
mMediaKeyEventSessionChangedCallbacks.put(listener, executor);
executor.execute(
() -> listener.onMediaKeyEventSessionChanged(
mCurMediaKeyEventSessionPackage, mCurMediaKeyEventSession));
- if (mMediaKeyEventSessionChangedCallbacks.size() == 1) {
- mService.addOnMediaKeyEventSessionChangedListener(
- mOnMediaKeyEventSessionChangedListenerStub);
- }
} catch (RemoteException e) {
- Log.e(TAG, "Failed to set media key listener", e);
+ Log.e(TAG, "Failed to add MediaKeyEventSessionChangedListener", e);
}
}
}
/**
- * Remove a {@link OnMediaKeyEventSessionChangedListener}.
+ * Stop receiving updates on media key event session change on the specified listener.
*
* @param listener A {@link OnMediaKeyEventSessionChangedListener}.
- * @hide
*/
- @SystemApi
- @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
public void removeOnMediaKeyEventSessionChangedListener(
@NonNull OnMediaKeyEventSessionChangedListener listener) {
Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
try {
- mMediaKeyEventSessionChangedCallbacks.remove(listener);
- if (mMediaKeyEventSessionChangedCallbacks.size() == 0) {
+ if (mMediaKeyEventSessionChangedCallbacks.remove(listener) != null
+ && mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
mService.removeOnMediaKeyEventSessionChangedListener(
mOnMediaKeyEventSessionChangedListenerStub);
}
} catch (RemoteException e) {
- Log.e(TAG, "Failed to set media key listener", e);
+ Log.e(TAG, "Failed to remove MediaKeyEventSessionChangedListener", e);
}
}
}
@@ -1124,16 +1192,14 @@
/**
* Listener to receive changes in the media key event session, which would receive a media key
* event unless specified.
- * @hide
*/
- @SystemApi
public interface OnMediaKeyEventSessionChangedListener {
/**
* Called when the media key session is changed to the given media session. The key event
* session is the media session which would receive key event by default, unless the caller
* has specified the target.
* <p>
- * The session token can be {@link null} if the media button session is unset. In that case,
+ * The session token can be {@code null} if the media button session is unset. In that case,
* packageName will return the package name of the last session's media button receiver, or
* an empty string if the last session didn't set a media button receiver.
*
diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java
index 0037b53..6a6a22c 100644
--- a/media/java/android/media/tv/tuner/Lnb.java
+++ b/media/java/android/media/tv/tuner/Lnb.java
@@ -20,7 +20,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.LnbEventType;
+import android.hardware.tv.tuner.LnbPosition;
+import android.hardware.tv.tuner.LnbTone;
+import android.hardware.tv.tuner.LnbVoltage;
import android.media.tv.tuner.Tuner.Result;
import java.lang.annotation.Retention;
@@ -48,39 +51,39 @@
/**
* LNB power voltage not set.
*/
- public static final int VOLTAGE_NONE = Constants.LnbVoltage.NONE;
+ public static final int VOLTAGE_NONE = LnbVoltage.NONE;
/**
* LNB power voltage 5V.
*/
- public static final int VOLTAGE_5V = Constants.LnbVoltage.VOLTAGE_5V;
+ public static final int VOLTAGE_5V = LnbVoltage.VOLTAGE_5V;
/**
* LNB power voltage 11V.
*/
- public static final int VOLTAGE_11V = Constants.LnbVoltage.VOLTAGE_11V;
+ public static final int VOLTAGE_11V = LnbVoltage.VOLTAGE_11V;
/**
* LNB power voltage 12V.
*/
- public static final int VOLTAGE_12V = Constants.LnbVoltage.VOLTAGE_12V;
+ public static final int VOLTAGE_12V = LnbVoltage.VOLTAGE_12V;
/**
* LNB power voltage 13V.
*/
- public static final int VOLTAGE_13V = Constants.LnbVoltage.VOLTAGE_13V;
+ public static final int VOLTAGE_13V = LnbVoltage.VOLTAGE_13V;
/**
* LNB power voltage 14V.
*/
- public static final int VOLTAGE_14V = Constants.LnbVoltage.VOLTAGE_14V;
+ public static final int VOLTAGE_14V = LnbVoltage.VOLTAGE_14V;
/**
* LNB power voltage 15V.
*/
- public static final int VOLTAGE_15V = Constants.LnbVoltage.VOLTAGE_15V;
+ public static final int VOLTAGE_15V = LnbVoltage.VOLTAGE_15V;
/**
* LNB power voltage 18V.
*/
- public static final int VOLTAGE_18V = Constants.LnbVoltage.VOLTAGE_18V;
+ public static final int VOLTAGE_18V = LnbVoltage.VOLTAGE_18V;
/**
* LNB power voltage 19V.
*/
- public static final int VOLTAGE_19V = Constants.LnbVoltage.VOLTAGE_19V;
+ public static final int VOLTAGE_19V = LnbVoltage.VOLTAGE_19V;
/** @hide */
@IntDef(prefix = "TONE_",
@@ -91,11 +94,11 @@
/**
* LNB tone mode not set.
*/
- public static final int TONE_NONE = Constants.LnbTone.NONE;
+ public static final int TONE_NONE = LnbTone.NONE;
/**
* LNB continuous tone mode.
*/
- public static final int TONE_CONTINUOUS = Constants.LnbTone.CONTINUOUS;
+ public static final int TONE_CONTINUOUS = LnbTone.CONTINUOUS;
/** @hide */
@IntDef(prefix = "POSITION_",
@@ -106,15 +109,15 @@
/**
* LNB position is not defined.
*/
- public static final int POSITION_UNDEFINED = Constants.LnbPosition.UNDEFINED;
+ public static final int POSITION_UNDEFINED = LnbPosition.UNDEFINED;
/**
* Position A of two-band LNBs
*/
- public static final int POSITION_A = Constants.LnbPosition.POSITION_A;
+ public static final int POSITION_A = LnbPosition.POSITION_A;
/**
* Position B of two-band LNBs
*/
- public static final int POSITION_B = Constants.LnbPosition.POSITION_B;
+ public static final int POSITION_B = LnbPosition.POSITION_B;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -126,22 +129,19 @@
/**
* Outgoing Diseqc message overflow.
*/
- public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW =
- Constants.LnbEventType.DISEQC_RX_OVERFLOW;
+ public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW = LnbEventType.DISEQC_RX_OVERFLOW;
/**
* Outgoing Diseqc message isn't delivered on time.
*/
- public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT =
- Constants.LnbEventType.DISEQC_RX_TIMEOUT;
+ public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT = LnbEventType.DISEQC_RX_TIMEOUT;
/**
* Incoming Diseqc message has parity error.
*/
- public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR =
- Constants.LnbEventType.DISEQC_RX_PARITY_ERROR;
+ public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR = LnbEventType.DISEQC_RX_PARITY_ERROR;
/**
* LNB is overload.
*/
- public static final int EVENT_TYPE_LNB_OVERLOAD = Constants.LnbEventType.LNB_OVERLOAD;
+ public static final int EVENT_TYPE_LNB_OVERLOAD = LnbEventType.LNB_OVERLOAD;
private static final String TAG = "Lnb";
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index a384bef..ed5e6ee 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -25,7 +25,9 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.Context;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.Constant;
+import android.hardware.tv.tuner.Constant64Bit;
+import android.hardware.tv.tuner.FrontendScanType;
import android.media.tv.TvInputService;
import android.media.tv.tuner.dvr.DvrPlayback;
import android.media.tv.tuner.dvr.DvrRecorder;
@@ -85,19 +87,19 @@
/**
* Invalid TS packet ID.
*/
- public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
+ public static final int INVALID_TS_PID = Constant.INVALID_TS_PID;
/**
* Invalid stream ID.
*/
- public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
+ public static final int INVALID_STREAM_ID = Constant.INVALID_STREAM_ID;
/**
* Invalid filter ID.
*/
- public static final int INVALID_FILTER_ID = Constants.Constant.INVALID_FILTER_ID;
+ public static final int INVALID_FILTER_ID = Constant.INVALID_FILTER_ID;
/**
* Invalid AV Sync ID.
*/
- public static final int INVALID_AV_SYNC_ID = Constants.Constant.INVALID_AV_SYNC_ID;
+ public static final int INVALID_AV_SYNC_ID = Constant.INVALID_AV_SYNC_ID;
/**
* Invalid timestamp.
*
@@ -113,7 +115,7 @@
* @see android.media.tv.tuner.filter.MmtpRecordEvent#getPts()
*/
public static final long INVALID_TIMESTAMP =
- android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_PRESENTATION_TIME_STAMP;
+ Constant64Bit.INVALID_PRESENTATION_TIME_STAMP;
/**
* Invalid mpu sequence number in MmtpRecordEvent.
*
@@ -123,8 +125,7 @@
* @see android.media.tv.tuner.filter.MmtpRecordEvent#getMpuSequenceNumber()
*/
public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM =
- android.hardware.tv.tuner.V1_1.Constants.Constant
- .INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM;
+ Constant.INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM;
/**
* Invalid first macroblock address in MmtpRecordEvent and TsRecordEvent.
*
@@ -135,7 +136,7 @@
* @see android.media.tv.tuner.filter.TsRecordEvent#getMbInSlice()
*/
public static final int INVALID_FIRST_MACROBLOCK_IN_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FIRST_MACROBLOCK_IN_SLICE;
+ Constant.INVALID_FIRST_MACROBLOCK_IN_SLICE;
/**
* Invalid local transport stream id.
*
@@ -144,30 +145,26 @@
*
* @see #linkFrontendToCiCam(int)
*/
- public static final int INVALID_LTS_ID =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LTS_ID;
+ public static final int INVALID_LTS_ID = Constant.INVALID_LTS_ID;
/**
* Invalid 64-bit filter ID.
*/
- public static final long INVALID_FILTER_ID_LONG =
- android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_FILTER_ID_64BIT;
+ public static final long INVALID_FILTER_ID_LONG = Constant64Bit.INVALID_FILTER_ID_64BIT;
/**
* Invalid frequency that is used as the default frontend frequency setting.
*/
public static final int INVALID_FRONTEND_SETTING_FREQUENCY =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FRONTEND_SETTING_FREQUENCY;
+ Constant.INVALID_FRONTEND_SETTING_FREQUENCY;
/**
* Invalid frontend id.
*/
- public static final int INVALID_FRONTEND_ID =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FRONTEND_ID;
+ public static final int INVALID_FRONTEND_ID = Constant.INVALID_FRONTEND_ID;
/**
* Invalid LNB id.
*
* @hide
*/
- public static final int INVALID_LNB_ID =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LNB_ID;
+ public static final int INVALID_LNB_ID = Constant.INVALID_LNB_ID;
/**
* A void key token. It is used to remove the current key from descrambler.
*
@@ -175,8 +172,7 @@
* to use this constant to remove current key before closing MediaCas session.
*/
@NonNull
- public static final byte[] VOID_KEYTOKEN =
- {android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_KEYTOKEN};
+ public static final byte[] VOID_KEYTOKEN = {Constant.INVALID_KEYTOKEN};
/** @hide */
@IntDef(prefix = "SCAN_TYPE_", value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_AUTO, SCAN_TYPE_BLIND})
@@ -185,20 +181,20 @@
/**
* Scan type undefined.
*/
- public static final int SCAN_TYPE_UNDEFINED = Constants.FrontendScanType.SCAN_UNDEFINED;
+ public static final int SCAN_TYPE_UNDEFINED = FrontendScanType.SCAN_UNDEFINED;
/**
* Scan type auto.
*
* <p> Tuner will send {@link android.media.tv.tuner.frontend.ScanCallback#onLocked}
*/
- public static final int SCAN_TYPE_AUTO = Constants.FrontendScanType.SCAN_AUTO;
+ public static final int SCAN_TYPE_AUTO = FrontendScanType.SCAN_AUTO;
/**
* Blind scan.
*
* <p>Frequency range is not specified. The {@link android.media.tv.tuner.Tuner} will scan an
* implementation specific range.
*/
- public static final int SCAN_TYPE_BLIND = Constants.FrontendScanType.SCAN_BLIND;
+ public static final int SCAN_TYPE_BLIND = FrontendScanType.SCAN_BLIND;
/** @hide */
@@ -210,31 +206,33 @@
/**
* Operation succeeded.
*/
- public static final int RESULT_SUCCESS = Constants.Result.SUCCESS;
+ public static final int RESULT_SUCCESS = android.hardware.tv.tuner.Result.SUCCESS;
/**
* Operation failed because the corresponding resources are not available.
*/
- public static final int RESULT_UNAVAILABLE = Constants.Result.UNAVAILABLE;
+ public static final int RESULT_UNAVAILABLE = android.hardware.tv.tuner.Result.UNAVAILABLE;
/**
* Operation failed because the corresponding resources are not initialized.
*/
- public static final int RESULT_NOT_INITIALIZED = Constants.Result.NOT_INITIALIZED;
+ public static final int RESULT_NOT_INITIALIZED =
+ android.hardware.tv.tuner.Result.NOT_INITIALIZED;
/**
* Operation failed because it's not in a valid state.
*/
- public static final int RESULT_INVALID_STATE = Constants.Result.INVALID_STATE;
+ public static final int RESULT_INVALID_STATE = android.hardware.tv.tuner.Result.INVALID_STATE;
/**
* Operation failed because there are invalid arguments.
*/
- public static final int RESULT_INVALID_ARGUMENT = Constants.Result.INVALID_ARGUMENT;
+ public static final int RESULT_INVALID_ARGUMENT =
+ android.hardware.tv.tuner.Result.INVALID_ARGUMENT;
/**
* Memory allocation failed.
*/
- public static final int RESULT_OUT_OF_MEMORY = Constants.Result.OUT_OF_MEMORY;
+ public static final int RESULT_OUT_OF_MEMORY = android.hardware.tv.tuner.Result.OUT_OF_MEMORY;
/**
* Operation failed due to unknown errors.
*/
- public static final int RESULT_UNKNOWN_ERROR = Constants.Result.UNKNOWN_ERROR;
+ public static final int RESULT_UNKNOWN_ERROR = android.hardware.tv.tuner.Result.UNKNOWN_ERROR;
@@ -257,12 +255,12 @@
* DVR for recording.
* @hide
*/
- public static final int DVR_TYPE_RECORD = Constants.DvrType.RECORD;
+ public static final int DVR_TYPE_RECORD = android.hardware.tv.tuner.DvrType.RECORD;
/**
* DVR for playback of recorded programs.
* @hide
*/
- public static final int DVR_TYPE_PLAYBACK = Constants.DvrType.PLAYBACK;
+ public static final int DVR_TYPE_PLAYBACK = android.hardware.tv.tuner.DvrType.PLAYBACK;
static {
try {
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index a13077c..3a15daf 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -17,7 +17,11 @@
package android.media.tv.tuner;
import android.annotation.Nullable;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxAlpFilterType;
+import android.hardware.tv.tuner.DemuxIpFilterType;
+import android.hardware.tv.tuner.DemuxMmtpFilterType;
+import android.hardware.tv.tuner.DemuxTlvFilterType;
+import android.hardware.tv.tuner.DemuxTsFilterType;
import android.media.tv.tuner.filter.Filter;
/**
@@ -37,44 +41,44 @@
if (mainType == Filter.TYPE_TS) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxTsFilterType.UNDEFINED;
+ return DemuxTsFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxTsFilterType.SECTION;
+ return DemuxTsFilterType.SECTION;
case Filter.SUBTYPE_PES:
- return Constants.DemuxTsFilterType.PES;
+ return DemuxTsFilterType.PES;
case Filter.SUBTYPE_TS:
- return Constants.DemuxTsFilterType.TS;
+ return DemuxTsFilterType.TS;
case Filter.SUBTYPE_AUDIO:
- return Constants.DemuxTsFilterType.AUDIO;
+ return DemuxTsFilterType.AUDIO;
case Filter.SUBTYPE_VIDEO:
- return Constants.DemuxTsFilterType.VIDEO;
+ return DemuxTsFilterType.VIDEO;
case Filter.SUBTYPE_PCR:
- return Constants.DemuxTsFilterType.PCR;
+ return DemuxTsFilterType.PCR;
case Filter.SUBTYPE_RECORD:
- return Constants.DemuxTsFilterType.RECORD;
+ return DemuxTsFilterType.RECORD;
case Filter.SUBTYPE_TEMI:
- return Constants.DemuxTsFilterType.TEMI;
+ return DemuxTsFilterType.TEMI;
default:
break;
}
} else if (mainType == Filter.TYPE_MMTP) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxMmtpFilterType.UNDEFINED;
+ return DemuxMmtpFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxMmtpFilterType.SECTION;
+ return DemuxMmtpFilterType.SECTION;
case Filter.SUBTYPE_PES:
- return Constants.DemuxMmtpFilterType.PES;
+ return DemuxMmtpFilterType.PES;
case Filter.SUBTYPE_MMTP:
- return Constants.DemuxMmtpFilterType.MMTP;
+ return DemuxMmtpFilterType.MMTP;
case Filter.SUBTYPE_AUDIO:
- return Constants.DemuxMmtpFilterType.AUDIO;
+ return DemuxMmtpFilterType.AUDIO;
case Filter.SUBTYPE_VIDEO:
- return Constants.DemuxMmtpFilterType.VIDEO;
+ return DemuxMmtpFilterType.VIDEO;
case Filter.SUBTYPE_RECORD:
- return Constants.DemuxMmtpFilterType.RECORD;
+ return DemuxMmtpFilterType.RECORD;
case Filter.SUBTYPE_DOWNLOAD:
- return Constants.DemuxMmtpFilterType.DOWNLOAD;
+ return DemuxMmtpFilterType.DOWNLOAD;
default:
break;
}
@@ -82,43 +86,43 @@
} else if (mainType == Filter.TYPE_IP) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxIpFilterType.UNDEFINED;
+ return DemuxIpFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxIpFilterType.SECTION;
+ return DemuxIpFilterType.SECTION;
case Filter.SUBTYPE_NTP:
- return Constants.DemuxIpFilterType.NTP;
+ return DemuxIpFilterType.NTP;
case Filter.SUBTYPE_IP_PAYLOAD:
- return Constants.DemuxIpFilterType.IP_PAYLOAD;
+ return DemuxIpFilterType.IP_PAYLOAD;
case Filter.SUBTYPE_IP:
- return Constants.DemuxIpFilterType.IP;
+ return DemuxIpFilterType.IP;
case Filter.SUBTYPE_PAYLOAD_THROUGH:
- return Constants.DemuxIpFilterType.PAYLOAD_THROUGH;
+ return DemuxIpFilterType.PAYLOAD_THROUGH;
default:
break;
}
} else if (mainType == Filter.TYPE_TLV) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxTlvFilterType.UNDEFINED;
+ return DemuxTlvFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxTlvFilterType.SECTION;
+ return DemuxTlvFilterType.SECTION;
case Filter.SUBTYPE_TLV:
- return Constants.DemuxTlvFilterType.TLV;
+ return DemuxTlvFilterType.TLV;
case Filter.SUBTYPE_PAYLOAD_THROUGH:
- return Constants.DemuxTlvFilterType.PAYLOAD_THROUGH;
+ return DemuxTlvFilterType.PAYLOAD_THROUGH;
default:
break;
}
} else if (mainType == Filter.TYPE_ALP) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxAlpFilterType.UNDEFINED;
+ return DemuxAlpFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxAlpFilterType.SECTION;
+ return DemuxAlpFilterType.SECTION;
case Filter.SUBTYPE_PTP:
- return Constants.DemuxAlpFilterType.PTP;
+ return DemuxAlpFilterType.PTP;
case Filter.SUBTYPE_PAYLOAD_THROUGH:
- return Constants.DemuxAlpFilterType.PAYLOAD_THROUGH;
+ return DemuxAlpFilterType.PAYLOAD_THROUGH;
default:
break;
}
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 6c2b9e3..cfd8583 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -20,7 +20,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
@@ -56,25 +55,27 @@
/**
* The space of the playback is empty.
*/
- public static final int PLAYBACK_STATUS_EMPTY = Constants.PlaybackStatus.SPACE_EMPTY;
+ public static final int PLAYBACK_STATUS_EMPTY =
+ android.hardware.tv.tuner.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;
+ android.hardware.tv.tuner.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;
+ android.hardware.tv.tuner.PlaybackStatus.SPACE_ALMOST_FULL;
/**
* The space of the playback is full.
*/
- public static final int PLAYBACK_STATUS_FULL = Constants.PlaybackStatus.SPACE_FULL;
+ public static final int PLAYBACK_STATUS_FULL =
+ android.hardware.tv.tuner.PlaybackStatus.SPACE_FULL;
private static final String TAG = "TvTunerPlayback";
diff --git a/media/java/android/media/tv/tuner/dvr/DvrSettings.java b/media/java/android/media/tv/tuner/dvr/DvrSettings.java
index 60f0d16..0c4af4b 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrSettings.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrSettings.java
@@ -20,7 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DataFormat;
import android.media.tv.tuner.filter.Filter;
import java.lang.annotation.Retention;
@@ -43,19 +43,19 @@
/**
* Transport Stream.
*/
- public static final int DATA_FORMAT_TS = Constants.DataFormat.TS;
+ public static final int DATA_FORMAT_TS = android.hardware.tv.tuner.DataFormat.TS;
/**
* Packetized Elementary Stream.
*/
- public static final int DATA_FORMAT_PES = Constants.DataFormat.PES;
+ public static final int DATA_FORMAT_PES = android.hardware.tv.tuner.DataFormat.PES;
/**
* Elementary Stream.
*/
- public static final int DATA_FORMAT_ES = Constants.DataFormat.ES;
+ public static final int DATA_FORMAT_ES = android.hardware.tv.tuner.DataFormat.ES;
/**
* TLV (type-length-value) Stream for SHV
*/
- public static final int DATA_FORMAT_SHV_TLV = Constants.DataFormat.SHV_TLV;
+ public static final int DATA_FORMAT_SHV_TLV = android.hardware.tv.tuner.DataFormat.SHV_TLV;
@Filter.Status
diff --git a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
index 29bc2c9..bac3b56 100644
--- a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxAlpLengthType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -63,17 +63,17 @@
/**
* Length type not defined.
*/
- public static final int LENGTH_TYPE_UNDEFINED = Constants.DemuxAlpLengthType.UNDEFINED;
+ public static final int LENGTH_TYPE_UNDEFINED = DemuxAlpLengthType.UNDEFINED;
/**
* Length does NOT include additional header.
*/
public static final int LENGTH_TYPE_WITHOUT_ADDITIONAL_HEADER =
- Constants.DemuxAlpLengthType.WITHOUT_ADDITIONAL_HEADER;
+ DemuxAlpLengthType.WITHOUT_ADDITIONAL_HEADER;
/**
* Length includes additional header.
*/
public static final int LENGTH_TYPE_WITH_ADDITIONAL_HEADER =
- Constants.DemuxAlpLengthType.WITH_ADDITIONAL_HEADER;
+ DemuxAlpLengthType.WITH_ADDITIONAL_HEADER;
private final int mPacketType;
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index 25457a7..8bcf3d2 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_1.Constants;
import android.media.tv.tuner.TunerUtils;
import android.media.tv.tuner.TunerVersionChecker;
@@ -46,55 +45,60 @@
/*
* Undefined Video stream type
*/
- public static final int VIDEO_STREAM_TYPE_UNDEFINED = Constants.VideoStreamType.UNDEFINED;
+ public static final int VIDEO_STREAM_TYPE_UNDEFINED =
+ android.hardware.tv.tuner.VideoStreamType.UNDEFINED;
/*
* ITU-T | ISO/IEC Reserved
*/
- public static final int VIDEO_STREAM_TYPE_RESERVED = Constants.VideoStreamType.RESERVED;
+ public static final int VIDEO_STREAM_TYPE_RESERVED =
+ android.hardware.tv.tuner.VideoStreamType.RESERVED;
/*
* ISO/IEC 11172
*/
- public static final int VIDEO_STREAM_TYPE_MPEG1 = Constants.VideoStreamType.MPEG1;
+ public static final int VIDEO_STREAM_TYPE_MPEG1 =
+ android.hardware.tv.tuner.VideoStreamType.MPEG1;
/*
* ITU-T Rec.H.262 and ISO/IEC 13818-2
*/
- public static final int VIDEO_STREAM_TYPE_MPEG2 = Constants.VideoStreamType.MPEG2;
+ public static final int VIDEO_STREAM_TYPE_MPEG2 =
+ android.hardware.tv.tuner.VideoStreamType.MPEG2;
/*
* ISO/IEC 14496-2 (MPEG-4 H.263 based video)
*/
- public static final int VIDEO_STREAM_TYPE_MPEG4P2 = Constants.VideoStreamType.MPEG4P2;
+ public static final int VIDEO_STREAM_TYPE_MPEG4P2 =
+ android.hardware.tv.tuner.VideoStreamType.MPEG4P2;
/*
* ITU-T Rec.H.264 and ISO/IEC 14496-10
*/
- public static final int VIDEO_STREAM_TYPE_AVC = Constants.VideoStreamType.AVC;
+ public static final int VIDEO_STREAM_TYPE_AVC = android.hardware.tv.tuner.VideoStreamType.AVC;
/*
* ITU-T Rec. H.265 and ISO/IEC 23008-2
*/
- public static final int VIDEO_STREAM_TYPE_HEVC = Constants.VideoStreamType.HEVC;
+ public static final int VIDEO_STREAM_TYPE_HEVC = android.hardware.tv.tuner.VideoStreamType.HEVC;
/*
* Microsoft VC.1
*/
- public static final int VIDEO_STREAM_TYPE_VC1 = Constants.VideoStreamType.VC1;
+ public static final int VIDEO_STREAM_TYPE_VC1 = android.hardware.tv.tuner.VideoStreamType.VC1;
/*
* Google VP8
*/
- public static final int VIDEO_STREAM_TYPE_VP8 = Constants.VideoStreamType.VP8;
+ public static final int VIDEO_STREAM_TYPE_VP8 = android.hardware.tv.tuner.VideoStreamType.VP8;
/*
* Google VP9
*/
- public static final int VIDEO_STREAM_TYPE_VP9 = Constants.VideoStreamType.VP9;
+ public static final int VIDEO_STREAM_TYPE_VP9 = android.hardware.tv.tuner.VideoStreamType.VP9;
/*
* AOMedia Video 1
*/
- public static final int VIDEO_STREAM_TYPE_AV1 = Constants.VideoStreamType.AV1;
+ public static final int VIDEO_STREAM_TYPE_AV1 = android.hardware.tv.tuner.VideoStreamType.AV1;
/*
* Chinese Standard
*/
- public static final int VIDEO_STREAM_TYPE_AVS = Constants.VideoStreamType.AVS;
+ public static final int VIDEO_STREAM_TYPE_AVS = android.hardware.tv.tuner.VideoStreamType.AVS;
/*
* New Chinese Standard
*/
- public static final int VIDEO_STREAM_TYPE_AVS2 = Constants.VideoStreamType.AVS2;
+ public static final int VIDEO_STREAM_TYPE_AVS2 = android.hardware.tv.tuner.VideoStreamType.AVS2;
/** @hide */
@IntDef(prefix = "AUDIO_STREAM_TYPE_",
@@ -110,67 +114,73 @@
/*
* Undefined Audio stream type
*/
- public static final int AUDIO_STREAM_TYPE_UNDEFINED = Constants.AudioStreamType.UNDEFINED;
+ public static final int AUDIO_STREAM_TYPE_UNDEFINED =
+ android.hardware.tv.tuner.AudioStreamType.UNDEFINED;
/*
* Uncompressed Audio
*/
- public static final int AUDIO_STREAM_TYPE_PCM = Constants.AudioStreamType.PCM;
+ public static final int AUDIO_STREAM_TYPE_PCM = android.hardware.tv.tuner.AudioStreamType.PCM;
/*
* MPEG Audio Layer III versions
*/
- public static final int AUDIO_STREAM_TYPE_MP3 = Constants.AudioStreamType.MP3;
+ public static final int AUDIO_STREAM_TYPE_MP3 = android.hardware.tv.tuner.AudioStreamType.MP3;
/*
* ISO/IEC 11172 Audio
*/
- public static final int AUDIO_STREAM_TYPE_MPEG1 = Constants.AudioStreamType.MPEG1;
+ public static final int AUDIO_STREAM_TYPE_MPEG1 =
+ android.hardware.tv.tuner.AudioStreamType.MPEG1;
/*
* ISO/IEC 13818-3
*/
- public static final int AUDIO_STREAM_TYPE_MPEG2 = Constants.AudioStreamType.MPEG2;
+ public static final int AUDIO_STREAM_TYPE_MPEG2 =
+ android.hardware.tv.tuner.AudioStreamType.MPEG2;
/*
* ISO/IEC 23008-3 (MPEG-H Part 3)
*/
- public static final int AUDIO_STREAM_TYPE_MPEGH = Constants.AudioStreamType.MPEGH;
+ public static final int AUDIO_STREAM_TYPE_MPEGH =
+ android.hardware.tv.tuner.AudioStreamType.MPEGH;
/*
* ISO/IEC 14496-3
*/
- public static final int AUDIO_STREAM_TYPE_AAC = Constants.AudioStreamType.AAC;
+ public static final int AUDIO_STREAM_TYPE_AAC = android.hardware.tv.tuner.AudioStreamType.AAC;
/*
* Dolby Digital
*/
- public static final int AUDIO_STREAM_TYPE_AC3 = Constants.AudioStreamType.AC3;
+ public static final int AUDIO_STREAM_TYPE_AC3 = android.hardware.tv.tuner.AudioStreamType.AC3;
/*
* Dolby Digital Plus
*/
- public static final int AUDIO_STREAM_TYPE_EAC3 = Constants.AudioStreamType.EAC3;
+ public static final int AUDIO_STREAM_TYPE_EAC3 = android.hardware.tv.tuner.AudioStreamType.EAC3;
/*
* Dolby AC-4
*/
- public static final int AUDIO_STREAM_TYPE_AC4 = Constants.AudioStreamType.AC4;
+ public static final int AUDIO_STREAM_TYPE_AC4 = android.hardware.tv.tuner.AudioStreamType.AC4;
/*
* Basic DTS
*/
- public static final int AUDIO_STREAM_TYPE_DTS = Constants.AudioStreamType.DTS;
+ public static final int AUDIO_STREAM_TYPE_DTS = android.hardware.tv.tuner.AudioStreamType.DTS;
/*
* High Resolution DTS
*/
- public static final int AUDIO_STREAM_TYPE_DTS_HD = Constants.AudioStreamType.DTS_HD;
+ public static final int AUDIO_STREAM_TYPE_DTS_HD =
+ android.hardware.tv.tuner.AudioStreamType.DTS_HD;
/*
* Windows Media Audio
*/
- public static final int AUDIO_STREAM_TYPE_WMA = Constants.AudioStreamType.WMA;
+ public static final int AUDIO_STREAM_TYPE_WMA = android.hardware.tv.tuner.AudioStreamType.WMA;
/*
* Opus Interactive Audio Codec
*/
- public static final int AUDIO_STREAM_TYPE_OPUS = Constants.AudioStreamType.OPUS;
+ public static final int AUDIO_STREAM_TYPE_OPUS = android.hardware.tv.tuner.AudioStreamType.OPUS;
/*
* VORBIS Interactive Audio Codec
*/
- public static final int AUDIO_STREAM_TYPE_VORBIS = Constants.AudioStreamType.VORBIS;
+ public static final int AUDIO_STREAM_TYPE_VORBIS =
+ android.hardware.tv.tuner.AudioStreamType.VORBIS;
/*
* SJ/T 11368-2006
*/
- public static final int AUDIO_STREAM_TYPE_DRA = Constants.AudioStreamType.DRA;
+ public static final int AUDIO_STREAM_TYPE_DRA = android.hardware.tv.tuner.AudioStreamType.DRA;
private final boolean mIsPassthrough;
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 3db7047..e7612bc 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -21,7 +21,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxFilterMainType;
+import android.hardware.tv.tuner.DemuxFilterMonitorEventType;
+import android.hardware.tv.tuner.DemuxFilterStatus;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
@@ -53,23 +55,23 @@
/**
* TS filter type.
*/
- public static final int TYPE_TS = Constants.DemuxFilterMainType.TS;
+ public static final int TYPE_TS = DemuxFilterMainType.TS;
/**
* MMTP filter type.
*/
- public static final int TYPE_MMTP = Constants.DemuxFilterMainType.MMTP;
+ public static final int TYPE_MMTP = DemuxFilterMainType.MMTP;
/**
* IP filter type.
*/
- public static final int TYPE_IP = Constants.DemuxFilterMainType.IP;
+ public static final int TYPE_IP = DemuxFilterMainType.IP;
/**
* TLV filter type.
*/
- public static final int TYPE_TLV = Constants.DemuxFilterMainType.TLV;
+ public static final int TYPE_TLV = DemuxFilterMainType.TLV;
/**
* ALP filter type.
*/
- public static final int TYPE_ALP = Constants.DemuxFilterMainType.ALP;
+ public static final int TYPE_ALP = DemuxFilterMainType.ALP;
/** @hide */
@IntDef(prefix = "SUBTYPE_",
@@ -158,7 +160,7 @@
/**
* The status of a filter that the data in the filter buffer is ready to be read.
*/
- public static final int STATUS_DATA_READY = Constants.DemuxFilterStatus.DATA_READY;
+ public static final int STATUS_DATA_READY = DemuxFilterStatus.DATA_READY;
/**
* The status of a filter that the amount of available data in the filter buffer is at low
* level.
@@ -166,19 +168,19 @@
* The value is set to 25 percent of the buffer size by default. It can be changed when
* configuring the filter.
*/
- public static final int STATUS_LOW_WATER = Constants.DemuxFilterStatus.LOW_WATER;
+ public static final int STATUS_LOW_WATER = DemuxFilterStatus.LOW_WATER;
/**
* The status of a filter that the amount of available data in the filter buffer is at high
* level.
* The value is set to 75 percent of the buffer size by default. It can be changed when
* configuring the filter.
*/
- public static final int STATUS_HIGH_WATER = Constants.DemuxFilterStatus.HIGH_WATER;
+ public static final int STATUS_HIGH_WATER = DemuxFilterStatus.HIGH_WATER;
/**
* The status of a filter that the filter buffer is full and newly filtered data is being
* discarded.
*/
- public static final int STATUS_OVERFLOW = Constants.DemuxFilterStatus.OVERFLOW;
+ public static final int STATUS_OVERFLOW = DemuxFilterStatus.OVERFLOW;
/** @hide */
@IntDef(flag = true,
@@ -192,17 +194,17 @@
* Content’s scrambling status is unknown
*/
public static final int SCRAMBLING_STATUS_UNKNOWN =
- android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.UNKNOWN;
+ android.hardware.tv.tuner.ScramblingStatus.UNKNOWN;
/**
* Content is not scrambled.
*/
public static final int SCRAMBLING_STATUS_NOT_SCRAMBLED =
- android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.NOT_SCRAMBLED;
+ android.hardware.tv.tuner.ScramblingStatus.NOT_SCRAMBLED;
/**
* Content is scrambled.
*/
public static final int SCRAMBLING_STATUS_SCRAMBLED =
- android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.SCRAMBLED;
+ android.hardware.tv.tuner.ScramblingStatus.SCRAMBLED;
/** @hide */
@IntDef(flag = true,
@@ -215,12 +217,11 @@
* Monitor scrambling status change.
*/
public static final int MONITOR_EVENT_SCRAMBLING_STATUS =
- android.hardware.tv.tuner.V1_1.Constants.DemuxFilterMonitorEventType.SCRAMBLING_STATUS;
+ DemuxFilterMonitorEventType.SCRAMBLING_STATUS;
/**
* Monitor ip cid change.
*/
- public static final int MONITOR_EVENT_IP_CID_CHANGE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxFilterMonitorEventType.IP_CID_CHANGE;
+ public static final int MONITOR_EVENT_IP_CID_CHANGE = DemuxFilterMonitorEventType.IP_CID_CHANGE;
private static final String TAG = "Filter";
diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
index 4b69807..6578464 100644
--- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.annotation.Size;
import android.annotation.SystemApi;
+import android.hardware.tv.tuner.Constant;
import android.media.tv.tuner.TunerVersionChecker;
/**
@@ -33,8 +34,7 @@
/**
* Undefined filter type.
*/
- public static final int INVALID_IP_FILTER_CONTEXT_ID =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_IP_FILTER_CONTEXT_ID;
+ public static final int INVALID_IP_FILTER_CONTEXT_ID = Constant.INVALID_IP_FILTER_CONTEXT_ID;
private final byte[] mSrcIpAddress;
private final byte[] mDstIpAddress;
diff --git a/media/java/android/media/tv/tuner/filter/RecordSettings.java b/media/java/android/media/tv/tuner/filter/RecordSettings.java
index 91992af..cd70365 100644
--- a/media/java/android/media/tv/tuner/filter/RecordSettings.java
+++ b/media/java/android/media/tv/tuner/filter/RecordSettings.java
@@ -19,7 +19,10 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxRecordScIndexType;
+import android.hardware.tv.tuner.DemuxScHevcIndex;
+import android.hardware.tv.tuner.DemuxScIndex;
+import android.hardware.tv.tuner.DemuxTsIndex;
import android.media.tv.tuner.TunerUtils;
import java.lang.annotation.Retention;
@@ -57,88 +60,80 @@
/**
* TS index FIRST_PACKET.
*/
- public static final int TS_INDEX_FIRST_PACKET = Constants.DemuxTsIndex.FIRST_PACKET;
+ public static final int TS_INDEX_FIRST_PACKET = DemuxTsIndex.FIRST_PACKET;
/**
* TS index PAYLOAD_UNIT_START_INDICATOR.
*/
public static final int TS_INDEX_PAYLOAD_UNIT_START_INDICATOR =
- Constants.DemuxTsIndex.PAYLOAD_UNIT_START_INDICATOR;
+ DemuxTsIndex.PAYLOAD_UNIT_START_INDICATOR;
/**
* TS index CHANGE_TO_NOT_SCRAMBLED.
*/
- public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED =
- Constants.DemuxTsIndex.CHANGE_TO_NOT_SCRAMBLED;
+ public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED = DemuxTsIndex.CHANGE_TO_NOT_SCRAMBLED;
/**
* TS index CHANGE_TO_EVEN_SCRAMBLED.
*/
public static final int TS_INDEX_CHANGE_TO_EVEN_SCRAMBLED =
- Constants.DemuxTsIndex.CHANGE_TO_EVEN_SCRAMBLED;
+ DemuxTsIndex.CHANGE_TO_EVEN_SCRAMBLED;
/**
* TS index CHANGE_TO_ODD_SCRAMBLED.
*/
- public static final int TS_INDEX_CHANGE_TO_ODD_SCRAMBLED =
- Constants.DemuxTsIndex.CHANGE_TO_ODD_SCRAMBLED;
+ public static final int TS_INDEX_CHANGE_TO_ODD_SCRAMBLED = DemuxTsIndex.CHANGE_TO_ODD_SCRAMBLED;
/**
* TS index DISCONTINUITY_INDICATOR.
*/
- public static final int TS_INDEX_DISCONTINUITY_INDICATOR =
- Constants.DemuxTsIndex.DISCONTINUITY_INDICATOR;
+ public static final int TS_INDEX_DISCONTINUITY_INDICATOR = DemuxTsIndex.DISCONTINUITY_INDICATOR;
/**
* TS index RANDOM_ACCESS_INDICATOR.
*/
- public static final int TS_INDEX_RANDOM_ACCESS_INDICATOR =
- Constants.DemuxTsIndex.RANDOM_ACCESS_INDICATOR;
+ public static final int TS_INDEX_RANDOM_ACCESS_INDICATOR = DemuxTsIndex.RANDOM_ACCESS_INDICATOR;
/**
* TS index PRIORITY_INDICATOR.
*/
- public static final int TS_INDEX_PRIORITY_INDICATOR = Constants.DemuxTsIndex.PRIORITY_INDICATOR;
+ public static final int TS_INDEX_PRIORITY_INDICATOR = DemuxTsIndex.PRIORITY_INDICATOR;
/**
* TS index PCR_FLAG.
*/
- public static final int TS_INDEX_PCR_FLAG = Constants.DemuxTsIndex.PCR_FLAG;
+ public static final int TS_INDEX_PCR_FLAG = DemuxTsIndex.PCR_FLAG;
/**
* TS index OPCR_FLAG.
*/
- public static final int TS_INDEX_OPCR_FLAG = Constants.DemuxTsIndex.OPCR_FLAG;
+ public static final int TS_INDEX_OPCR_FLAG = DemuxTsIndex.OPCR_FLAG;
/**
* TS index SPLICING_POINT_FLAG.
*/
- public static final int TS_INDEX_SPLICING_POINT_FLAG =
- Constants.DemuxTsIndex.SPLICING_POINT_FLAG;
+ public static final int TS_INDEX_SPLICING_POINT_FLAG = DemuxTsIndex.SPLICING_POINT_FLAG;
/**
* TS index PRIVATE_DATA.
*/
- public static final int TS_INDEX_PRIVATE_DATA = Constants.DemuxTsIndex.PRIVATE_DATA;
+ public static final int TS_INDEX_PRIVATE_DATA = DemuxTsIndex.PRIVATE_DATA;
/**
* TS index ADAPTATION_EXTENSION_FLAG.
*/
public static final int TS_INDEX_ADAPTATION_EXTENSION_FLAG =
- Constants.DemuxTsIndex.ADAPTATION_EXTENSION_FLAG;
+ DemuxTsIndex.ADAPTATION_EXTENSION_FLAG;
/**
* Index the address of MPEG Media Transport Packet Table(MPT).
*/
- public static final int MPT_INDEX_MPT =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_MPT;
+ public static final int MPT_INDEX_MPT = DemuxTsIndex.MPT_INDEX_MPT;
/**
* Index the address of Video.
*/
- public static final int MPT_INDEX_VIDEO =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_VIDEO;
+ public static final int MPT_INDEX_VIDEO = DemuxTsIndex.MPT_INDEX_VIDEO;
/**
* Index the address of Audio.
*/
- public static final int MPT_INDEX_AUDIO =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_AUDIO;
+ public static final int MPT_INDEX_AUDIO = DemuxTsIndex.MPT_INDEX_AUDIO;
/**
* Index to indicate this is a target of timestamp extraction for video.
*/
public static final int MPT_INDEX_TIMESTAMP_TARGET_VIDEO =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_VIDEO;
+ DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_VIDEO;
/**
* Index to indicate this is a target of timestamp extraction for audio.
*/
public static final int MPT_INDEX_TIMESTAMP_TARGET_AUDIO =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_AUDIO;
+ DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_AUDIO;
/** @hide */
@@ -150,15 +145,15 @@
/**
* Start Code Index is not used.
*/
- public static final int INDEX_TYPE_NONE = Constants.DemuxRecordScIndexType.NONE;
+ public static final int INDEX_TYPE_NONE = DemuxRecordScIndexType.NONE;
/**
* Start Code index.
*/
- public static final int INDEX_TYPE_SC = Constants.DemuxRecordScIndexType.SC;
+ public static final int INDEX_TYPE_SC = DemuxRecordScIndexType.SC;
/**
* Start Code index for HEVC.
*/
- public static final int INDEX_TYPE_SC_HEVC = Constants.DemuxRecordScIndexType.SC_HEVC;
+ public static final int INDEX_TYPE_SC_HEVC = DemuxRecordScIndexType.SC_HEVC;
/**
* Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
@@ -176,44 +171,39 @@
/**
* SC index for a new I-frame.
*/
- public static final int SC_INDEX_I_FRAME = Constants.DemuxScIndex.I_FRAME;
+ public static final int SC_INDEX_I_FRAME = DemuxScIndex.I_FRAME;
/**
* SC index for a new P-frame.
*/
- public static final int SC_INDEX_P_FRAME = Constants.DemuxScIndex.P_FRAME;
+ public static final int SC_INDEX_P_FRAME = DemuxScIndex.P_FRAME;
/**
* SC index for a new B-frame.
*/
- public static final int SC_INDEX_B_FRAME = Constants.DemuxScIndex.B_FRAME;
+ public static final int SC_INDEX_B_FRAME = DemuxScIndex.B_FRAME;
/**
* SC index for a new sequence.
*/
- public static final int SC_INDEX_SEQUENCE = Constants.DemuxScIndex.SEQUENCE;
+ public static final int SC_INDEX_SEQUENCE = DemuxScIndex.SEQUENCE;
/**
* All blocks are coded as I blocks.
*/
- public static final int SC_INDEX_I_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.I_SLICE;
+ public static final int SC_INDEX_I_SLICE = DemuxScIndex.I_SLICE;
/**
* Blocks are coded as I or P blocks.
*/
- public static final int SC_INDEX_P_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.P_SLICE;
+ public static final int SC_INDEX_P_SLICE = DemuxScIndex.P_SLICE;
/**
* Blocks are coded as I, P or B blocks.
*/
- public static final int SC_INDEX_B_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.B_SLICE;
+ public static final int SC_INDEX_B_SLICE = DemuxScIndex.B_SLICE;
/**
* A so-called switching I slice that is coded.
*/
- public static final int SC_INDEX_SI_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.SI_SLICE;
+ public static final int SC_INDEX_SI_SLICE = DemuxScIndex.SI_SLICE;
/**
* A so-called switching P slice that is coded.
*/
- public static final int SC_INDEX_SP_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.SP_SLICE;
+ public static final int SC_INDEX_SP_SLICE = DemuxScIndex.SP_SLICE;
/**
* Indexes can be tagged by NAL unit group in HEVC according to ISO/IEC 23008-2.
@@ -231,41 +221,35 @@
/**
* SC HEVC index SPS.
*/
- public static final int SC_HEVC_INDEX_SPS = Constants.DemuxScHevcIndex.SPS;
+ public static final int SC_HEVC_INDEX_SPS = DemuxScHevcIndex.SPS;
/**
* SC HEVC index AUD.
*/
- public static final int SC_HEVC_INDEX_AUD = Constants.DemuxScHevcIndex.AUD;
+ public static final int SC_HEVC_INDEX_AUD = DemuxScHevcIndex.AUD;
/**
* SC HEVC index SLICE_CE_BLA_W_LP.
*/
- public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP =
- Constants.DemuxScHevcIndex.SLICE_CE_BLA_W_LP;
+ public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP = DemuxScHevcIndex.SLICE_CE_BLA_W_LP;
/**
* SC HEVC index SLICE_BLA_W_RADL.
*/
- public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL =
- Constants.DemuxScHevcIndex.SLICE_BLA_W_RADL;
+ public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL = DemuxScHevcIndex.SLICE_BLA_W_RADL;
/**
* SC HEVC index SLICE_BLA_N_LP.
*/
- public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP =
- Constants.DemuxScHevcIndex.SLICE_BLA_N_LP;
+ public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP = DemuxScHevcIndex.SLICE_BLA_N_LP;
/**
* SC HEVC index SLICE_IDR_W_RADL.
*/
- public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL =
- Constants.DemuxScHevcIndex.SLICE_IDR_W_RADL;
+ public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL = DemuxScHevcIndex.SLICE_IDR_W_RADL;
/**
* SC HEVC index SLICE_IDR_N_LP.
*/
- public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP =
- Constants.DemuxScHevcIndex.SLICE_IDR_N_LP;
+ public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP = DemuxScHevcIndex.SLICE_IDR_N_LP;
/**
* SC HEVC index SLICE_TRAIL_CRA.
*/
- public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA =
- Constants.DemuxScHevcIndex.SLICE_TRAIL_CRA;
+ public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA = DemuxScHevcIndex.SLICE_TRAIL_CRA;
/**
* @hide
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
index b2c3fd2..768f1d3 100644
--- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
@@ -20,7 +20,9 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAnalogAftFlag;
+import android.hardware.tv.tuner.FrontendAnalogSifStandard;
+import android.hardware.tv.tuner.FrontendAnalogType;
import android.media.tv.tuner.TunerVersionChecker;
import java.lang.annotation.Retention;
@@ -45,39 +47,39 @@
/**
* Undefined analog signal type.
*/
- public static final int SIGNAL_TYPE_UNDEFINED = Constants.FrontendAnalogType.UNDEFINED;
+ public static final int SIGNAL_TYPE_UNDEFINED = FrontendAnalogType.UNDEFINED;
/**
* AUTO analog signal type.
*/
- public static final int SIGNAL_TYPE_AUTO = Constants.FrontendAnalogType.AUTO;
+ public static final int SIGNAL_TYPE_AUTO = FrontendAnalogType.AUTO;
/**
* PAL analog signal type.
*/
- public static final int SIGNAL_TYPE_PAL = Constants.FrontendAnalogType.PAL;
+ public static final int SIGNAL_TYPE_PAL = FrontendAnalogType.PAL;
/**
* PAL M analog signal type.
*/
- public static final int SIGNAL_TYPE_PAL_M = Constants.FrontendAnalogType.PAL_M;
+ public static final int SIGNAL_TYPE_PAL_M = FrontendAnalogType.PAL_M;
/**
* PAL N analog signal type.
*/
- public static final int SIGNAL_TYPE_PAL_N = Constants.FrontendAnalogType.PAL_N;
+ public static final int SIGNAL_TYPE_PAL_N = FrontendAnalogType.PAL_N;
/**
* PAL 60 analog signal type.
*/
- public static final int SIGNAL_TYPE_PAL_60 = Constants.FrontendAnalogType.PAL_60;
+ public static final int SIGNAL_TYPE_PAL_60 = FrontendAnalogType.PAL_60;
/**
* NTSC analog signal type.
*/
- public static final int SIGNAL_TYPE_NTSC = Constants.FrontendAnalogType.NTSC;
+ public static final int SIGNAL_TYPE_NTSC = FrontendAnalogType.NTSC;
/**
* NTSC 443 analog signal type.
*/
- public static final int SIGNAL_TYPE_NTSC_443 = Constants.FrontendAnalogType.NTSC_443;
+ public static final int SIGNAL_TYPE_NTSC_443 = FrontendAnalogType.NTSC_443;
/**
* SECM analog signal type.
*/
- public static final int SIGNAL_TYPE_SECAM = Constants.FrontendAnalogType.SECAM;
+ public static final int SIGNAL_TYPE_SECAM = FrontendAnalogType.SECAM;
/** @hide */
@IntDef(flag = true,
@@ -91,79 +93,79 @@
/**
* Undefined Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_UNDEFINED = Constants.FrontendAnalogSifStandard.UNDEFINED;
+ public static final int SIF_UNDEFINED = FrontendAnalogSifStandard.UNDEFINED;
/**
* Audo Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_AUTO = Constants.FrontendAnalogSifStandard.AUTO;
+ public static final int SIF_AUTO = FrontendAnalogSifStandard.AUTO;
/**
* BG Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_BG = Constants.FrontendAnalogSifStandard.BG;
+ public static final int SIF_BG = FrontendAnalogSifStandard.BG;
/**
* BG-A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_BG_A2 = Constants.FrontendAnalogSifStandard.BG_A2;
+ public static final int SIF_BG_A2 = FrontendAnalogSifStandard.BG_A2;
/**
* BG-NICAM Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_BG_NICAM = Constants.FrontendAnalogSifStandard.BG_NICAM;
+ public static final int SIF_BG_NICAM = FrontendAnalogSifStandard.BG_NICAM;
/**
* I Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_I = Constants.FrontendAnalogSifStandard.I;
+ public static final int SIF_I = FrontendAnalogSifStandard.I;
/**
* DK Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK = Constants.FrontendAnalogSifStandard.DK;
+ public static final int SIF_DK = FrontendAnalogSifStandard.DK;
/**
* DK1 A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK1_A2 = Constants.FrontendAnalogSifStandard.DK1_A2;
+ public static final int SIF_DK1_A2 = FrontendAnalogSifStandard.DK1_A2;
/**
* DK2 A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK2_A2 = Constants.FrontendAnalogSifStandard.DK2_A2;
+ public static final int SIF_DK2_A2 = FrontendAnalogSifStandard.DK2_A2;
/**
* DK3 A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK3_A2 = Constants.FrontendAnalogSifStandard.DK3_A2;
+ public static final int SIF_DK3_A2 = FrontendAnalogSifStandard.DK3_A2;
/**
* DK-NICAM Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK_NICAM = Constants.FrontendAnalogSifStandard.DK_NICAM;
+ public static final int SIF_DK_NICAM = FrontendAnalogSifStandard.DK_NICAM;
/**
* L Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_L = Constants.FrontendAnalogSifStandard.L;
+ public static final int SIF_L = FrontendAnalogSifStandard.L;
/**
* M Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_M = Constants.FrontendAnalogSifStandard.M;
+ public static final int SIF_M = FrontendAnalogSifStandard.M;
/**
* M-BTSC Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_M_BTSC = Constants.FrontendAnalogSifStandard.M_BTSC;
+ public static final int SIF_M_BTSC = FrontendAnalogSifStandard.M_BTSC;
/**
* M-A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_M_A2 = Constants.FrontendAnalogSifStandard.M_A2;
+ public static final int SIF_M_A2 = FrontendAnalogSifStandard.M_A2;
/**
* M-EIAJ Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_M_EIAJ = Constants.FrontendAnalogSifStandard.M_EIAJ;
+ public static final int SIF_M_EIAJ = FrontendAnalogSifStandard.M_EIAJ;
/**
* I-NICAM Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_I_NICAM = Constants.FrontendAnalogSifStandard.I_NICAM;
+ public static final int SIF_I_NICAM = FrontendAnalogSifStandard.I_NICAM;
/**
* L-NICAM Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_L_NICAM = Constants.FrontendAnalogSifStandard.L_NICAM;
+ public static final int SIF_L_NICAM = FrontendAnalogSifStandard.L_NICAM;
/**
* L-PRIME Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_L_PRIME = Constants.FrontendAnalogSifStandard.L_PRIME;
+ public static final int SIF_L_PRIME = FrontendAnalogSifStandard.L_PRIME;
/** @hide */
@IntDef(prefix = "AFT_FLAG_",
@@ -174,18 +176,15 @@
/**
* Aft flag is not defined.
*/
- public static final int AFT_FLAG_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.UNDEFINED;
+ public static final int AFT_FLAG_UNDEFINED = FrontendAnalogAftFlag.UNDEFINED;
/**
* Aft flag is set true.
*/
- public static final int AFT_FLAG_TRUE =
- android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_TRUE;
+ public static final int AFT_FLAG_TRUE = FrontendAnalogAftFlag.AFT_TRUE;
/**
* Aft flag is not set.
*/
- public static final int AFT_FLAG_FALSE =
- android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_FALSE;
+ public static final int AFT_FLAG_FALSE = FrontendAnalogAftFlag.AFT_FALSE;
private final int mSignalType;
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
index ed1ce2d..52a20cb 100644
--- a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
@@ -20,7 +20,12 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAtsc3Bandwidth;
+import android.hardware.tv.tuner.FrontendAtsc3CodeRate;
+import android.hardware.tv.tuner.FrontendAtsc3DemodOutputFormat;
+import android.hardware.tv.tuner.FrontendAtsc3Fec;
+import android.hardware.tv.tuner.FrontendAtsc3Modulation;
+import android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -44,27 +49,23 @@
/**
* Bandwidth not defined.
*/
- public static final int BANDWIDTH_UNDEFINED =
- Constants.FrontendAtsc3Bandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendAtsc3Bandwidth.UNDEFINED;
/**
* Hardware is able to detect and set bandwidth automatically
*/
- public static final int BANDWIDTH_AUTO = Constants.FrontendAtsc3Bandwidth.AUTO;
+ public static final int BANDWIDTH_AUTO = FrontendAtsc3Bandwidth.AUTO;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_BANDWIDTH_6MHZ =
- Constants.FrontendAtsc3Bandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_BANDWIDTH_6MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_6MHZ;
/**
* 7 MHz bandwidth.
*/
- public static final int BANDWIDTH_BANDWIDTH_7MHZ =
- Constants.FrontendAtsc3Bandwidth.BANDWIDTH_7MHZ;
+ public static final int BANDWIDTH_BANDWIDTH_7MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_7MHZ;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_BANDWIDTH_8MHZ =
- Constants.FrontendAtsc3Bandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_BANDWIDTH_8MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_8MHZ;
/** @hide */
@@ -80,35 +81,35 @@
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendAtsc3Modulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendAtsc3Modulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically.
*/
- public static final int MODULATION_AUTO = Constants.FrontendAtsc3Modulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendAtsc3Modulation.AUTO;
/**
* QPSK modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendAtsc3Modulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendAtsc3Modulation.MOD_QPSK;
/**
* 16QAM modulation.
*/
- public static final int MODULATION_MOD_16QAM = Constants.FrontendAtsc3Modulation.MOD_16QAM;
+ public static final int MODULATION_MOD_16QAM = FrontendAtsc3Modulation.MOD_16QAM;
/**
* 64QAM modulation.
*/
- public static final int MODULATION_MOD_64QAM = Constants.FrontendAtsc3Modulation.MOD_64QAM;
+ public static final int MODULATION_MOD_64QAM = FrontendAtsc3Modulation.MOD_64QAM;
/**
* 256QAM modulation.
*/
- public static final int MODULATION_MOD_256QAM = Constants.FrontendAtsc3Modulation.MOD_256QAM;
+ public static final int MODULATION_MOD_256QAM = FrontendAtsc3Modulation.MOD_256QAM;
/**
* 1024QAM modulation.
*/
- public static final int MODULATION_MOD_1024QAM = Constants.FrontendAtsc3Modulation.MOD_1024QAM;
+ public static final int MODULATION_MOD_1024QAM = FrontendAtsc3Modulation.MOD_1024QAM;
/**
* 4096QAM modulation.
*/
- public static final int MODULATION_MOD_4096QAM = Constants.FrontendAtsc3Modulation.MOD_4096QAM;
+ public static final int MODULATION_MOD_4096QAM = FrontendAtsc3Modulation.MOD_4096QAM;
/** @hide */
@@ -123,22 +124,19 @@
* Time interleave mode undefined.
*/
public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
- Constants.FrontendAtsc3TimeInterleaveMode.UNDEFINED;
+ FrontendAtsc3TimeInterleaveMode.UNDEFINED;
/**
* Hardware is able to detect and set Time Interleave Mode automatically.
*/
- public static final int TIME_INTERLEAVE_MODE_AUTO =
- Constants.FrontendAtsc3TimeInterleaveMode.AUTO;
+ public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendAtsc3TimeInterleaveMode.AUTO;
/**
* CTI Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_CTI =
- Constants.FrontendAtsc3TimeInterleaveMode.CTI;
+ public static final int TIME_INTERLEAVE_MODE_CTI = FrontendAtsc3TimeInterleaveMode.CTI;
/**
* HTI Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_HTI =
- Constants.FrontendAtsc3TimeInterleaveMode.HTI;
+ public static final int TIME_INTERLEAVE_MODE_HTI = FrontendAtsc3TimeInterleaveMode.HTI;
/** @hide */
@@ -153,59 +151,59 @@
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED = Constants.FrontendAtsc3CodeRate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendAtsc3CodeRate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically
*/
- public static final int CODERATE_AUTO = Constants.FrontendAtsc3CodeRate.AUTO;
+ public static final int CODERATE_AUTO = FrontendAtsc3CodeRate.AUTO;
/**
* 2/15 code rate.
*/
- public static final int CODERATE_2_15 = Constants.FrontendAtsc3CodeRate.CODERATE_2_15;
+ public static final int CODERATE_2_15 = FrontendAtsc3CodeRate.CODERATE_2_15;
/**
* 3/15 code rate.
*/
- public static final int CODERATE_3_15 = Constants.FrontendAtsc3CodeRate.CODERATE_3_15;
+ public static final int CODERATE_3_15 = FrontendAtsc3CodeRate.CODERATE_3_15;
/**
* 4/15 code rate.
*/
- public static final int CODERATE_4_15 = Constants.FrontendAtsc3CodeRate.CODERATE_4_15;
+ public static final int CODERATE_4_15 = FrontendAtsc3CodeRate.CODERATE_4_15;
/**
* 5/15 code rate.
*/
- public static final int CODERATE_5_15 = Constants.FrontendAtsc3CodeRate.CODERATE_5_15;
+ public static final int CODERATE_5_15 = FrontendAtsc3CodeRate.CODERATE_5_15;
/**
* 6/15 code rate.
*/
- public static final int CODERATE_6_15 = Constants.FrontendAtsc3CodeRate.CODERATE_6_15;
+ public static final int CODERATE_6_15 = FrontendAtsc3CodeRate.CODERATE_6_15;
/**
* 7/15 code rate.
*/
- public static final int CODERATE_7_15 = Constants.FrontendAtsc3CodeRate.CODERATE_7_15;
+ public static final int CODERATE_7_15 = FrontendAtsc3CodeRate.CODERATE_7_15;
/**
* 8/15 code rate.
*/
- public static final int CODERATE_8_15 = Constants.FrontendAtsc3CodeRate.CODERATE_8_15;
+ public static final int CODERATE_8_15 = FrontendAtsc3CodeRate.CODERATE_8_15;
/**
* 9/15 code rate.
*/
- public static final int CODERATE_9_15 = Constants.FrontendAtsc3CodeRate.CODERATE_9_15;
+ public static final int CODERATE_9_15 = FrontendAtsc3CodeRate.CODERATE_9_15;
/**
* 10/15 code rate.
*/
- public static final int CODERATE_10_15 = Constants.FrontendAtsc3CodeRate.CODERATE_10_15;
+ public static final int CODERATE_10_15 = FrontendAtsc3CodeRate.CODERATE_10_15;
/**
* 11/15 code rate.
*/
- public static final int CODERATE_11_15 = Constants.FrontendAtsc3CodeRate.CODERATE_11_15;
+ public static final int CODERATE_11_15 = FrontendAtsc3CodeRate.CODERATE_11_15;
/**
* 12/15 code rate.
*/
- public static final int CODERATE_12_15 = Constants.FrontendAtsc3CodeRate.CODERATE_12_15;
+ public static final int CODERATE_12_15 = FrontendAtsc3CodeRate.CODERATE_12_15;
/**
* 13/15 code rate.
*/
- public static final int CODERATE_13_15 = Constants.FrontendAtsc3CodeRate.CODERATE_13_15;
+ public static final int CODERATE_13_15 = FrontendAtsc3CodeRate.CODERATE_13_15;
/** @hide */
@@ -219,35 +217,35 @@
/**
* Forward Error Correction undefined.
*/
- public static final int FEC_UNDEFINED = Constants.FrontendAtsc3Fec.UNDEFINED;
+ public static final int FEC_UNDEFINED = FrontendAtsc3Fec.UNDEFINED;
/**
* Hardware is able to detect and set FEC automatically
*/
- public static final int FEC_AUTO = Constants.FrontendAtsc3Fec.AUTO;
+ public static final int FEC_AUTO = FrontendAtsc3Fec.AUTO;
/**
* BCH LDPC 16K Forward Error Correction
*/
- public static final int FEC_BCH_LDPC_16K = Constants.FrontendAtsc3Fec.BCH_LDPC_16K;
+ public static final int FEC_BCH_LDPC_16K = FrontendAtsc3Fec.BCH_LDPC_16K;
/**
* BCH LDPC 64K Forward Error Correction
*/
- public static final int FEC_BCH_LDPC_64K = Constants.FrontendAtsc3Fec.BCH_LDPC_64K;
+ public static final int FEC_BCH_LDPC_64K = FrontendAtsc3Fec.BCH_LDPC_64K;
/**
* CRC LDPC 16K Forward Error Correction
*/
- public static final int FEC_CRC_LDPC_16K = Constants.FrontendAtsc3Fec.CRC_LDPC_16K;
+ public static final int FEC_CRC_LDPC_16K = FrontendAtsc3Fec.CRC_LDPC_16K;
/**
* CRC LDPC 64K Forward Error Correction
*/
- public static final int FEC_CRC_LDPC_64K = Constants.FrontendAtsc3Fec.CRC_LDPC_64K;
+ public static final int FEC_CRC_LDPC_64K = FrontendAtsc3Fec.CRC_LDPC_64K;
/**
* LDPC 16K Forward Error Correction
*/
- public static final int FEC_LDPC_16K = Constants.FrontendAtsc3Fec.LDPC_16K;
+ public static final int FEC_LDPC_16K = FrontendAtsc3Fec.LDPC_16K;
/**
* LDPC 64K Forward Error Correction
*/
- public static final int FEC_LDPC_64K = Constants.FrontendAtsc3Fec.LDPC_64K;
+ public static final int FEC_LDPC_64K = FrontendAtsc3Fec.LDPC_64K;
/** @hide */
@@ -262,17 +260,17 @@
* Demod output format undefined.
*/
public static final int DEMOD_OUTPUT_FORMAT_UNDEFINED =
- Constants.FrontendAtsc3DemodOutputFormat.UNDEFINED;
+ FrontendAtsc3DemodOutputFormat.UNDEFINED;
/**
* ALP format. Typically used in US region.
*/
public static final int DEMOD_OUTPUT_FORMAT_ATSC3_LINKLAYER_PACKET =
- Constants.FrontendAtsc3DemodOutputFormat.ATSC3_LINKLAYER_PACKET;
+ FrontendAtsc3DemodOutputFormat.ATSC3_LINKLAYER_PACKET;
/**
* BaseBand packet format. Typically used in Korea region.
*/
public static final int DEMOD_OUTPUT_FORMAT_BASEBAND_PACKET =
- Constants.FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
+ FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
private final int mBandwidth;
private final int mDemodOutputFormat;
diff --git a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
index f7244bb..042bba8 100644
--- a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
@@ -20,7 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAtscModulation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -44,19 +44,19 @@
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendAtscModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendAtscModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendAtscModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendAtscModulation.AUTO;
/**
* 8VSB Modulation.
*/
- public static final int MODULATION_MOD_8VSB = Constants.FrontendAtscModulation.MOD_8VSB;
+ public static final int MODULATION_MOD_8VSB = FrontendAtscModulation.MOD_8VSB;
/**
* 16VSB Modulation.
*/
- public static final int MODULATION_MOD_16VSB = Constants.FrontendAtscModulation.MOD_16VSB;
+ public static final int MODULATION_MOD_16VSB = FrontendAtscModulation.MOD_16VSB;
private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
index c1d0833..9ba41d5 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
@@ -21,6 +21,12 @@
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.hardware.tv.tuner.FrontendDtmbBandwidth;
+import android.hardware.tv.tuner.FrontendDtmbCodeRate;
+import android.hardware.tv.tuner.FrontendDtmbGuardInterval;
+import android.hardware.tv.tuner.FrontendDtmbModulation;
+import android.hardware.tv.tuner.FrontendDtmbTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDtmbTransmissionMode;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -46,23 +52,19 @@
/**
* Bandwidth not defined.
*/
- public static final int BANDWIDTH_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendDtmbBandwidth.UNDEFINED;
/**
* Hardware is able to detect and set bandwidth automatically
*/
- public static final int BANDWIDTH_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.AUTO;
+ public static final int BANDWIDTH_AUTO = FrontendDtmbBandwidth.AUTO;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_6MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_6MHZ = FrontendDtmbBandwidth.BANDWIDTH_6MHZ;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_8MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_8MHZ = FrontendDtmbBandwidth.BANDWIDTH_8MHZ;
/** @hide */
@@ -77,22 +79,21 @@
* Time Interleave Mode undefined.
*/
public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.UNDEFINED;
+ FrontendDtmbTimeInterleaveMode.UNDEFINED;
/**
* Hardware is able to detect and set time interleave mode automatically
*/
- public static final int TIME_INTERLEAVE_MODE_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.AUTO;
+ public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendDtmbTimeInterleaveMode.AUTO;
/**
* Time Interleave Mode timer int 240.
*/
public static final int TIME_INTERLEAVE_MODE_TIMER_INT_240 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.TIMER_INT_240;
+ FrontendDtmbTimeInterleaveMode.TIMER_INT_240;
/**
* Time Interleave Mode timer int 720.
*/
public static final int TIME_INTERLEAVE_MODE_TIMER_INT_720 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.TIMER_INT_720;
+ FrontendDtmbTimeInterleaveMode.TIMER_INT_720;
/** @hide */
@@ -108,43 +109,37 @@
/**
* Guard Interval undefined.
*/
- public static final int GUARD_INTERVAL_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.UNDEFINED;
+ public static final int GUARD_INTERVAL_UNDEFINED = FrontendDtmbGuardInterval.UNDEFINED;
/**
* Hardware is able to detect and set Guard Interval automatically.
*/
- public static final int GUARD_INTERVAL_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.AUTO;
+ public static final int GUARD_INTERVAL_AUTO = FrontendDtmbGuardInterval.AUTO;
/**
* PN_420_VARIOUS Guard Interval.
*/
public static final int GUARD_INTERVAL_PN_420_VARIOUS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_420_VARIOUS;
+ FrontendDtmbGuardInterval.PN_420_VARIOUS;
/**
* PN_595_CONST Guard Interval.
*/
- public static final int GUARD_INTERVAL_PN_595_CONST =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_595_CONST;
+ public static final int GUARD_INTERVAL_PN_595_CONST = FrontendDtmbGuardInterval.PN_595_CONST;
/**
* PN_945_VARIOUS Guard Interval.
*/
public static final int GUARD_INTERVAL_PN_945_VARIOUS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_945_VARIOUS;
+ FrontendDtmbGuardInterval.PN_945_VARIOUS;
/**
* PN_420_CONST Guard Interval.
*/
- public static final int GUARD_INTERVAL_PN_420_CONST =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_420_CONST;
+ public static final int GUARD_INTERVAL_PN_420_CONST = FrontendDtmbGuardInterval.PN_420_CONST;
/**
* PN_945_CONST Guard Interval.
*/
- public static final int GUARD_INTERVAL_PN_945_CONST =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_945_CONST;
+ public static final int GUARD_INTERVAL_PN_945_CONST = FrontendDtmbGuardInterval.PN_945_CONST;
/**
* PN_RESERVED Guard Interval.
*/
- public static final int GUARD_INTERVAL_PN_RESERVED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_RESERVED;
+ public static final int GUARD_INTERVAL_PN_RESERVED = FrontendDtmbGuardInterval.PN_RESERVED;
/** @hide */
@@ -160,38 +155,36 @@
/**
* Constellation not defined.
*/
- public static final int MODULATION_CONSTELLATION_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.UNDEFINED;
+ public static final int MODULATION_CONSTELLATION_UNDEFINED = FrontendDtmbModulation.UNDEFINED;
/**
* Hardware is able to detect and set Constellation automatically.
*/
- public static final int MODULATION_CONSTELLATION_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.AUTO;
+ public static final int MODULATION_CONSTELLATION_AUTO = FrontendDtmbModulation.AUTO;
/**
* 4QAM Constellation.
*/
public static final int MODULATION_CONSTELLATION_4QAM =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_4QAM;
+ FrontendDtmbModulation.CONSTELLATION_4QAM;
/**
* 4QAM_NR Constellation.
*/
public static final int MODULATION_CONSTELLATION_4QAM_NR =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_4QAM_NR;
+ FrontendDtmbModulation.CONSTELLATION_4QAM_NR;
/**
* 16QAM Constellation.
*/
public static final int MODULATION_CONSTELLATION_16QAM =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_16QAM;
+ FrontendDtmbModulation.CONSTELLATION_16QAM;
/**
* 32QAM Constellation.
*/
public static final int MODULATION_CONSTELLATION_32QAM =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_32QAM;
+ FrontendDtmbModulation.CONSTELLATION_32QAM;
/**
* 64QAM Constellation.
*/
public static final int MODULATION_CONSTELLATION_64QAM =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_64QAM;
+ FrontendDtmbModulation.CONSTELLATION_64QAM;
/** @hide */
@IntDef(flag = true,
@@ -203,28 +196,23 @@
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendDtmbCodeRate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically.
*/
- public static final int CODERATE_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.AUTO;
+ public static final int CODERATE_AUTO = FrontendDtmbCodeRate.AUTO;
/**
* 2/5 code rate.
*/
- public static final int CODERATE_2_5 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_2_5;
+ public static final int CODERATE_2_5 = FrontendDtmbCodeRate.CODERATE_2_5;
/**
* 3/5 code rate.
*/
- public static final int CODERATE_3_5 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_3_5;
+ public static final int CODERATE_3_5 = FrontendDtmbCodeRate.CODERATE_3_5;
/**
* 4/5 code rate.
*/
- public static final int CODERATE_4_5 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_4_5;
+ public static final int CODERATE_4_5 = FrontendDtmbCodeRate.CODERATE_4_5;
/** @hide */
@IntDef(flag = true,
@@ -237,23 +225,19 @@
/**
* Transmission Mode undefined.
*/
- public static final int TRANSMISSION_MODE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.UNDEFINED;
+ public static final int TRANSMISSION_MODE_UNDEFINED = FrontendDtmbTransmissionMode.UNDEFINED;
/**
* Hardware is able to detect and set Transmission Mode automatically
*/
- public static final int TRANSMISSION_MODE_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.AUTO;
+ public static final int TRANSMISSION_MODE_AUTO = FrontendDtmbTransmissionMode.AUTO;
/**
* C1 Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_C1 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.C1;
+ public static final int TRANSMISSION_MODE_C1 = FrontendDtmbTransmissionMode.C1;
/**
* C3780 Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_C3780 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.C3780;
+ public static final int TRANSMISSION_MODE_C3780 = FrontendDtmbTransmissionMode.C3780;
private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
index db28631..b209d97 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
@@ -20,7 +20,11 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendCableTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDvbcAnnex;
+import android.hardware.tv.tuner.FrontendDvbcBandwidth;
+import android.hardware.tv.tuner.FrontendDvbcModulation;
+import android.hardware.tv.tuner.FrontendDvbcOuterFec;
import android.media.tv.tuner.TunerVersionChecker;
import android.media.tv.tuner.frontend.FrontendSettings.FrontendSpectralInversion;
@@ -47,31 +51,31 @@
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendDvbcModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendDvbcModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendDvbcModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendDvbcModulation.AUTO;
/**
* 16QAM Modulation.
*/
- public static final int MODULATION_MOD_16QAM = Constants.FrontendDvbcModulation.MOD_16QAM;
+ public static final int MODULATION_MOD_16QAM = FrontendDvbcModulation.MOD_16QAM;
/**
* 32QAM Modulation.
*/
- public static final int MODULATION_MOD_32QAM = Constants.FrontendDvbcModulation.MOD_32QAM;
+ public static final int MODULATION_MOD_32QAM = FrontendDvbcModulation.MOD_32QAM;
/**
* 64QAM Modulation.
*/
- public static final int MODULATION_MOD_64QAM = Constants.FrontendDvbcModulation.MOD_64QAM;
+ public static final int MODULATION_MOD_64QAM = FrontendDvbcModulation.MOD_64QAM;
/**
* 128QAM Modulation.
*/
- public static final int MODULATION_MOD_128QAM = Constants.FrontendDvbcModulation.MOD_128QAM;
+ public static final int MODULATION_MOD_128QAM = FrontendDvbcModulation.MOD_128QAM;
/**
* 256QAM Modulation.
*/
- public static final int MODULATION_MOD_256QAM = Constants.FrontendDvbcModulation.MOD_256QAM;
+ public static final int MODULATION_MOD_256QAM = FrontendDvbcModulation.MOD_256QAM;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -82,16 +86,15 @@
/**
* Outer Forward Error Correction (FEC) Type undefined.
*/
- public static final int OUTER_FEC_UNDEFINED = Constants.FrontendDvbcOuterFec.UNDEFINED;
+ public static final int OUTER_FEC_UNDEFINED = FrontendDvbcOuterFec.UNDEFINED;
/**
* None Outer Forward Error Correction (FEC) Type.
*/
- public static final int OUTER_FEC_OUTER_FEC_NONE =
- Constants.FrontendDvbcOuterFec.OUTER_FEC_NONE;
+ public static final int OUTER_FEC_OUTER_FEC_NONE = FrontendDvbcOuterFec.OUTER_FEC_NONE;
/**
* RS Outer Forward Error Correction (FEC) Type.
*/
- public static final int OUTER_FEC_OUTER_FEC_RS = Constants.FrontendDvbcOuterFec.OUTER_FEC_RS;
+ public static final int OUTER_FEC_OUTER_FEC_RS = FrontendDvbcOuterFec.OUTER_FEC_RS;
/** @hide */
@@ -104,19 +107,19 @@
/**
* Annex Type undefined.
*/
- public static final int ANNEX_UNDEFINED = Constants.FrontendDvbcAnnex.UNDEFINED;
+ public static final int ANNEX_UNDEFINED = FrontendDvbcAnnex.UNDEFINED;
/**
* Annex Type A.
*/
- public static final int ANNEX_A = Constants.FrontendDvbcAnnex.A;
+ public static final int ANNEX_A = FrontendDvbcAnnex.A;
/**
* Annex Type B.
*/
- public static final int ANNEX_B = Constants.FrontendDvbcAnnex.B;
+ public static final int ANNEX_B = FrontendDvbcAnnex.B;
/**
* Annex Type C.
*/
- public static final int ANNEX_C = Constants.FrontendDvbcAnnex.C;
+ public static final int ANNEX_C = FrontendDvbcAnnex.C;
/**
@@ -137,7 +140,7 @@
*/
@Deprecated
public static final int SPECTRAL_INVERSION_UNDEFINED =
- Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+ android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
/**
* Normal Spectral Inversion.
*
@@ -145,7 +148,7 @@
*/
@Deprecated
public static final int SPECTRAL_INVERSION_NORMAL =
- Constants.FrontendDvbcSpectralInversion.NORMAL;
+ android.hardware.tv.tuner.FrontendSpectralInversion.NORMAL;
/**
* Inverted Spectral Inversion.
*
@@ -153,7 +156,7 @@
*/
@Deprecated
public static final int SPECTRAL_INVERSION_INVERTED =
- Constants.FrontendDvbcSpectralInversion.INVERTED;
+ android.hardware.tv.tuner.FrontendSpectralInversion.INVERTED;
/** @hide */
@IntDef(flag = true,
@@ -171,57 +174,56 @@
* Time interleave mode undefined.
*/
public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.UNDEFINED;
+ FrontendCableTimeInterleaveMode.UNDEFINED;
/**
* Hardware is able to detect and set Time Interleave Mode automatically.
*/
- public static final int TIME_INTERLEAVE_MODE_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.AUTO;
+ public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendCableTimeInterleaveMode.AUTO;
/**
* 128/1/0 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_1_0 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_0;
+ public static final int TIME_INTERLEAVE_MODE_128_1_0 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_0;
/**
* 128/1/1 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_1_1 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_1;
+ public static final int TIME_INTERLEAVE_MODE_128_1_1 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_1;
/**
* 64/2 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_64_2 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_64_2;
+ public static final int TIME_INTERLEAVE_MODE_64_2 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_64_2;
/**
* 32/4 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_32_4 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_32_4;
+ public static final int TIME_INTERLEAVE_MODE_32_4 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_32_4;
/**
* 16/8 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_16_8 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_16_8;
+ public static final int TIME_INTERLEAVE_MODE_16_8 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_16_8;
/**
* 8/16 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_8_16 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_8_16;
+ public static final int TIME_INTERLEAVE_MODE_8_16 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_8_16;
/**
* 128/2 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_2 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_2;
+ public static final int TIME_INTERLEAVE_MODE_128_2 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_2;
/**
* 128/3 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_3 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_3;
+ public static final int TIME_INTERLEAVE_MODE_128_3 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_3;
/**
* 128/4 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_4 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_4;
+ public static final int TIME_INTERLEAVE_MODE_128_4 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_4;
/** @hide */
@IntDef(flag = true,
@@ -234,28 +236,23 @@
/**
* Bandwidth undefined.
*/
- public static final int BANDWIDTH_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendDvbcBandwidth.UNDEFINED;
/**
* 5 MHz bandwidth.
*/
- public static final int BANDWIDTH_5MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_5MHZ;
+ public static final int BANDWIDTH_5MHZ = FrontendDvbcBandwidth.BANDWIDTH_5MHZ;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_6MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_6MHZ = FrontendDvbcBandwidth.BANDWIDTH_6MHZ;
/**
* 7 MHz bandwidth.
*/
- public static final int BANDWIDTH_7MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_7MHZ;
+ public static final int BANDWIDTH_7MHZ = FrontendDvbcBandwidth.BANDWIDTH_7MHZ;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_8MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_8MHZ = FrontendDvbcBandwidth.BANDWIDTH_8MHZ;
private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index f68d554..6e3d98a 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -21,7 +21,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendDvbsModulation;
+import android.hardware.tv.tuner.FrontendDvbsPilot;
+import android.hardware.tv.tuner.FrontendDvbsRolloff;
+import android.hardware.tv.tuner.FrontendDvbsScanType;
+import android.hardware.tv.tuner.FrontendDvbsStandard;
+import android.hardware.tv.tuner.FrontendDvbsVcmMode;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.TunerVersionChecker;
@@ -47,32 +52,27 @@
/**
* Dvbs scan type undefined.
*/
- public static final int SCAN_TYPE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNDEFINED;
+ public static final int SCAN_TYPE_UNDEFINED = FrontendDvbsScanType.UNDEFINED;
/**
* Dvbs scan type DIRECT.
*/
- public static final int SCAN_TYPE_DIRECT =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DIRECT;
+ public static final int SCAN_TYPE_DIRECT = FrontendDvbsScanType.DIRECT;
/**
* Dvbs scan type DISEQC.
*/
- public static final int SCAN_TYPE_DISEQC =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DISEQC;
+ public static final int SCAN_TYPE_DISEQC = FrontendDvbsScanType.DISEQC;
/**
* Dvbs scan type UNICABLE.
*/
- public static final int SCAN_TYPE_UNICABLE =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNICABLE;
+ public static final int SCAN_TYPE_UNICABLE = FrontendDvbsScanType.UNICABLE;
/**
* Dvbs scan type JESS.
*/
- public static final int SCAN_TYPE_JESS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.JESS;
+ public static final int SCAN_TYPE_JESS = FrontendDvbsScanType.JESS;
/** @hide */
@IntDef(flag = true,
@@ -88,63 +88,63 @@
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendDvbsModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendDvbsModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendDvbsModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendDvbsModulation.AUTO;
/**
* QPSK Modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendDvbsModulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendDvbsModulation.MOD_QPSK;
/**
* 8PSK Modulation.
*/
- public static final int MODULATION_MOD_8PSK = Constants.FrontendDvbsModulation.MOD_8PSK;
+ public static final int MODULATION_MOD_8PSK = FrontendDvbsModulation.MOD_8PSK;
/**
* 16QAM Modulation.
*/
- public static final int MODULATION_MOD_16QAM = Constants.FrontendDvbsModulation.MOD_16QAM;
+ public static final int MODULATION_MOD_16QAM = FrontendDvbsModulation.MOD_16QAM;
/**
* 16PSK Modulation.
*/
- public static final int MODULATION_MOD_16PSK = Constants.FrontendDvbsModulation.MOD_16PSK;
+ public static final int MODULATION_MOD_16PSK = FrontendDvbsModulation.MOD_16PSK;
/**
* 32PSK Modulation.
*/
- public static final int MODULATION_MOD_32PSK = Constants.FrontendDvbsModulation.MOD_32PSK;
+ public static final int MODULATION_MOD_32PSK = FrontendDvbsModulation.MOD_32PSK;
/**
* ACM Modulation.
*/
- public static final int MODULATION_MOD_ACM = Constants.FrontendDvbsModulation.MOD_ACM;
+ public static final int MODULATION_MOD_ACM = FrontendDvbsModulation.MOD_ACM;
/**
* 8APSK Modulation.
*/
- public static final int MODULATION_MOD_8APSK = Constants.FrontendDvbsModulation.MOD_8APSK;
+ public static final int MODULATION_MOD_8APSK = FrontendDvbsModulation.MOD_8APSK;
/**
* 16APSK Modulation.
*/
- public static final int MODULATION_MOD_16APSK = Constants.FrontendDvbsModulation.MOD_16APSK;
+ public static final int MODULATION_MOD_16APSK = FrontendDvbsModulation.MOD_16APSK;
/**
* 32APSK Modulation.
*/
- public static final int MODULATION_MOD_32APSK = Constants.FrontendDvbsModulation.MOD_32APSK;
+ public static final int MODULATION_MOD_32APSK = FrontendDvbsModulation.MOD_32APSK;
/**
* 64APSK Modulation.
*/
- public static final int MODULATION_MOD_64APSK = Constants.FrontendDvbsModulation.MOD_64APSK;
+ public static final int MODULATION_MOD_64APSK = FrontendDvbsModulation.MOD_64APSK;
/**
* 128APSK Modulation.
*/
- public static final int MODULATION_MOD_128APSK = Constants.FrontendDvbsModulation.MOD_128APSK;
+ public static final int MODULATION_MOD_128APSK = FrontendDvbsModulation.MOD_128APSK;
/**
* 256APSK Modulation.
*/
- public static final int MODULATION_MOD_256APSK = Constants.FrontendDvbsModulation.MOD_256APSK;
+ public static final int MODULATION_MOD_256APSK = FrontendDvbsModulation.MOD_256APSK;
/**
* Reversed Modulation.
*/
- public static final int MODULATION_MOD_RESERVED = Constants.FrontendDvbsModulation.MOD_RESERVED;
+ public static final int MODULATION_MOD_RESERVED = FrontendDvbsModulation.MOD_RESERVED;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -156,31 +156,31 @@
/**
* Rolloff range undefined.
*/
- public static final int ROLLOFF_UNDEFINED = Constants.FrontendDvbsRolloff.UNDEFINED;
+ public static final int ROLLOFF_UNDEFINED = FrontendDvbsRolloff.UNDEFINED;
/**
* Rolloff range 0,35.
*/
- public static final int ROLLOFF_0_35 = Constants.FrontendDvbsRolloff.ROLLOFF_0_35;
+ public static final int ROLLOFF_0_35 = FrontendDvbsRolloff.ROLLOFF_0_35;
/**
* Rolloff range 0,25.
*/
- public static final int ROLLOFF_0_25 = Constants.FrontendDvbsRolloff.ROLLOFF_0_25;
+ public static final int ROLLOFF_0_25 = FrontendDvbsRolloff.ROLLOFF_0_25;
/**
* Rolloff range 0,20.
*/
- public static final int ROLLOFF_0_20 = Constants.FrontendDvbsRolloff.ROLLOFF_0_20;
+ public static final int ROLLOFF_0_20 = FrontendDvbsRolloff.ROLLOFF_0_20;
/**
* Rolloff range 0,15.
*/
- public static final int ROLLOFF_0_15 = Constants.FrontendDvbsRolloff.ROLLOFF_0_15;
+ public static final int ROLLOFF_0_15 = FrontendDvbsRolloff.ROLLOFF_0_15;
/**
* Rolloff range 0,10.
*/
- public static final int ROLLOFF_0_10 = Constants.FrontendDvbsRolloff.ROLLOFF_0_10;
+ public static final int ROLLOFF_0_10 = FrontendDvbsRolloff.ROLLOFF_0_10;
/**
* Rolloff range 0,5.
*/
- public static final int ROLLOFF_0_5 = Constants.FrontendDvbsRolloff.ROLLOFF_0_5;
+ public static final int ROLLOFF_0_5 = FrontendDvbsRolloff.ROLLOFF_0_5;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -191,19 +191,19 @@
/**
* Pilot mode undefined.
*/
- public static final int PILOT_UNDEFINED = Constants.FrontendDvbsPilot.UNDEFINED;
+ public static final int PILOT_UNDEFINED = FrontendDvbsPilot.UNDEFINED;
/**
* Pilot mode on.
*/
- public static final int PILOT_ON = Constants.FrontendDvbsPilot.ON;
+ public static final int PILOT_ON = FrontendDvbsPilot.ON;
/**
* Pilot mode off.
*/
- public static final int PILOT_OFF = Constants.FrontendDvbsPilot.OFF;
+ public static final int PILOT_OFF = FrontendDvbsPilot.OFF;
/**
* Pilot mode auto.
*/
- public static final int PILOT_AUTO = Constants.FrontendDvbsPilot.AUTO;
+ public static final int PILOT_AUTO = FrontendDvbsPilot.AUTO;
/** @hide */
@@ -216,19 +216,19 @@
/**
* Standard undefined.
*/
- public static final int STANDARD_AUTO = Constants.FrontendDvbsStandard.AUTO;
+ public static final int STANDARD_AUTO = FrontendDvbsStandard.AUTO;
/**
* Standard S.
*/
- public static final int STANDARD_S = Constants.FrontendDvbsStandard.S;
+ public static final int STANDARD_S = FrontendDvbsStandard.S;
/**
* Standard S2.
*/
- public static final int STANDARD_S2 = Constants.FrontendDvbsStandard.S2;
+ public static final int STANDARD_S2 = FrontendDvbsStandard.S2;
/**
* Standard S2X.
*/
- public static final int STANDARD_S2X = Constants.FrontendDvbsStandard.S2X;
+ public static final int STANDARD_S2X = FrontendDvbsStandard.S2X;
/** @hide */
@IntDef(prefix = "VCM_MODE_",
@@ -239,15 +239,15 @@
/**
* VCM mode undefined.
*/
- public static final int VCM_MODE_UNDEFINED = Constants.FrontendDvbsVcmMode.UNDEFINED;
+ public static final int VCM_MODE_UNDEFINED = FrontendDvbsVcmMode.UNDEFINED;
/**
* Auto VCM mode.
*/
- public static final int VCM_MODE_AUTO = Constants.FrontendDvbsVcmMode.AUTO;
+ public static final int VCM_MODE_AUTO = FrontendDvbsVcmMode.AUTO;
/**
* Manual VCM mode.
*/
- public static final int VCM_MODE_MANUAL = Constants.FrontendDvbsVcmMode.MANUAL;
+ public static final int VCM_MODE_MANUAL = FrontendDvbsVcmMode.MANUAL;
private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index 536c7b8..5735b39 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -20,7 +20,14 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendDvbtBandwidth;
+import android.hardware.tv.tuner.FrontendDvbtCoderate;
+import android.hardware.tv.tuner.FrontendDvbtConstellation;
+import android.hardware.tv.tuner.FrontendDvbtGuardInterval;
+import android.hardware.tv.tuner.FrontendDvbtHierarchy;
+import android.hardware.tv.tuner.FrontendDvbtPlpMode;
+import android.hardware.tv.tuner.FrontendDvbtStandard;
+import android.hardware.tv.tuner.FrontendDvbtTransmissionMode;
import android.media.tv.tuner.TunerVersionChecker;
import java.lang.annotation.Retention;
@@ -46,51 +53,49 @@
/**
* Transmission Mode undefined.
*/
- public static final int TRANSMISSION_MODE_UNDEFINED =
- Constants.FrontendDvbtTransmissionMode.UNDEFINED;
+ public static final int TRANSMISSION_MODE_UNDEFINED = FrontendDvbtTransmissionMode.UNDEFINED;
/**
* Hardware is able to detect and set Transmission Mode automatically
*/
- public static final int TRANSMISSION_MODE_AUTO = Constants.FrontendDvbtTransmissionMode.AUTO;
+ public static final int TRANSMISSION_MODE_AUTO = FrontendDvbtTransmissionMode.AUTO;
/**
* 2K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_2K = Constants.FrontendDvbtTransmissionMode.MODE_2K;
+ public static final int TRANSMISSION_MODE_2K = FrontendDvbtTransmissionMode.MODE_2K;
/**
* 8K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_8K = Constants.FrontendDvbtTransmissionMode.MODE_8K;
+ public static final int TRANSMISSION_MODE_8K = FrontendDvbtTransmissionMode.MODE_8K;
/**
* 4K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_4K = Constants.FrontendDvbtTransmissionMode.MODE_4K;
+ public static final int TRANSMISSION_MODE_4K = FrontendDvbtTransmissionMode.MODE_4K;
/**
* 1K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_1K = Constants.FrontendDvbtTransmissionMode.MODE_1K;
+ public static final int TRANSMISSION_MODE_1K = FrontendDvbtTransmissionMode.MODE_1K;
/**
* 16K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_16K = Constants.FrontendDvbtTransmissionMode.MODE_16K;
+ public static final int TRANSMISSION_MODE_16K = FrontendDvbtTransmissionMode.MODE_16K;
/**
* 32K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_32K = Constants.FrontendDvbtTransmissionMode.MODE_32K;
+ public static final int TRANSMISSION_MODE_32K = FrontendDvbtTransmissionMode.MODE_32K;
/**
* 8K Transmission Extended Mode.
*/
- public static final int TRANSMISSION_MODE_EXTENDED_8K =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_8K_E;
+ public static final int TRANSMISSION_MODE_EXTENDED_8K = FrontendDvbtTransmissionMode.MODE_8K_E;
/**
* 16K Transmission Extended Mode.
*/
public static final int TRANSMISSION_MODE_EXTENDED_16K =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_16K_E;
+ FrontendDvbtTransmissionMode.MODE_16K_E;
/**
* 32K Transmission Extended Mode.
*/
public static final int TRANSMISSION_MODE_EXTENDED_32K =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_32K_E;
+ FrontendDvbtTransmissionMode.MODE_32K_E;
/** @hide */
@IntDef(flag = true,
@@ -103,35 +108,35 @@
/**
* Bandwidth undefined.
*/
- public static final int BANDWIDTH_UNDEFINED = Constants.FrontendDvbtBandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendDvbtBandwidth.UNDEFINED;
/**
* Hardware is able to detect and set Bandwidth automatically.
*/
- public static final int BANDWIDTH_AUTO = Constants.FrontendDvbtBandwidth.AUTO;
+ public static final int BANDWIDTH_AUTO = FrontendDvbtBandwidth.AUTO;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_8MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_8MHZ = FrontendDvbtBandwidth.BANDWIDTH_8MHZ;
/**
* 7 MHz bandwidth.
*/
- public static final int BANDWIDTH_7MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_7MHZ;
+ public static final int BANDWIDTH_7MHZ = FrontendDvbtBandwidth.BANDWIDTH_7MHZ;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_6MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_6MHZ = FrontendDvbtBandwidth.BANDWIDTH_6MHZ;
/**
* 5 MHz bandwidth.
*/
- public static final int BANDWIDTH_5MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_5MHZ;
+ public static final int BANDWIDTH_5MHZ = FrontendDvbtBandwidth.BANDWIDTH_5MHZ;
/**
* 1,7 MHz bandwidth.
*/
- public static final int BANDWIDTH_1_7MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_1_7MHZ;
+ public static final int BANDWIDTH_1_7MHZ = FrontendDvbtBandwidth.BANDWIDTH_1_7MHZ;
/**
* 10 MHz bandwidth.
*/
- public static final int BANDWIDTH_10MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_10MHZ;
+ public static final int BANDWIDTH_10MHZ = FrontendDvbtBandwidth.BANDWIDTH_10MHZ;
/** @hide */
@@ -147,55 +152,44 @@
/**
* Constellation not defined.
*/
- public static final int CONSTELLATION_UNDEFINED = Constants.FrontendDvbtConstellation.UNDEFINED;
+ public static final int CONSTELLATION_UNDEFINED = FrontendDvbtConstellation.UNDEFINED;
/**
* Hardware is able to detect and set Constellation automatically.
*/
- public static final int CONSTELLATION_AUTO = Constants.FrontendDvbtConstellation.AUTO;
+ public static final int CONSTELLATION_AUTO = FrontendDvbtConstellation.AUTO;
/**
* QPSK Constellation.
*/
- public static final int CONSTELLATION_QPSK =
- Constants.FrontendDvbtConstellation.CONSTELLATION_QPSK;
+ public static final int CONSTELLATION_QPSK = FrontendDvbtConstellation.CONSTELLATION_QPSK;
/**
* 16QAM Constellation.
*/
- public static final int CONSTELLATION_16QAM =
- Constants.FrontendDvbtConstellation.CONSTELLATION_16QAM;
+ public static final int CONSTELLATION_16QAM = FrontendDvbtConstellation.CONSTELLATION_16QAM;
/**
* 64QAM Constellation.
*/
- public static final int CONSTELLATION_64QAM =
- Constants.FrontendDvbtConstellation.CONSTELLATION_64QAM;
+ public static final int CONSTELLATION_64QAM = FrontendDvbtConstellation.CONSTELLATION_64QAM;
/**
* 256QAM Constellation.
*/
- public static final int CONSTELLATION_256QAM =
- Constants.FrontendDvbtConstellation.CONSTELLATION_256QAM;
+ public static final int CONSTELLATION_256QAM = FrontendDvbtConstellation.CONSTELLATION_256QAM;
/**
* QPSK Rotated Constellation.
*/
- public static final int CONSTELLATION_QPSK_R =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
- .CONSTELLATION_QPSK_R;
+ public static final int CONSTELLATION_QPSK_R = FrontendDvbtConstellation.CONSTELLATION_QPSK_R;
/**
* 16QAM Rotated Constellation.
*/
- public static final int CONSTELLATION_16QAM_R =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
- .CONSTELLATION_16QAM_R;
+ public static final int CONSTELLATION_16QAM_R = FrontendDvbtConstellation.CONSTELLATION_16QAM_R;
/**
* 64QAM Rotated Constellation.
*/
- public static final int CONSTELLATION_64QAM_R =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
- .CONSTELLATION_64QAM_R;
+ public static final int CONSTELLATION_64QAM_R = FrontendDvbtConstellation.CONSTELLATION_64QAM_R;
/**
* 256QAM Rotated Constellation.
*/
public static final int CONSTELLATION_256QAM_R =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
- .CONSTELLATION_256QAM_R;
+ FrontendDvbtConstellation.CONSTELLATION_256QAM_R;
/** @hide */
@IntDef(flag = true,
@@ -209,48 +203,43 @@
/**
* Hierarchy undefined.
*/
- public static final int HIERARCHY_UNDEFINED = Constants.FrontendDvbtHierarchy.UNDEFINED;
+ public static final int HIERARCHY_UNDEFINED = FrontendDvbtHierarchy.UNDEFINED;
/**
* Hardware is able to detect and set Hierarchy automatically.
*/
- public static final int HIERARCHY_AUTO = Constants.FrontendDvbtHierarchy.AUTO;
+ public static final int HIERARCHY_AUTO = FrontendDvbtHierarchy.AUTO;
/**
* Non-native Hierarchy
*/
- public static final int HIERARCHY_NON_NATIVE =
- Constants.FrontendDvbtHierarchy.HIERARCHY_NON_NATIVE;
+ public static final int HIERARCHY_NON_NATIVE = FrontendDvbtHierarchy.HIERARCHY_NON_NATIVE;
/**
* 1-native Hierarchy
*/
- public static final int HIERARCHY_1_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_1_NATIVE;
+ public static final int HIERARCHY_1_NATIVE = FrontendDvbtHierarchy.HIERARCHY_1_NATIVE;
/**
* 2-native Hierarchy
*/
- public static final int HIERARCHY_2_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_2_NATIVE;
+ public static final int HIERARCHY_2_NATIVE = FrontendDvbtHierarchy.HIERARCHY_2_NATIVE;
/**
* 4-native Hierarchy
*/
- public static final int HIERARCHY_4_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_4_NATIVE;
+ public static final int HIERARCHY_4_NATIVE = FrontendDvbtHierarchy.HIERARCHY_4_NATIVE;
/**
* Non-indepth Hierarchy
*/
- public static final int HIERARCHY_NON_INDEPTH =
- Constants.FrontendDvbtHierarchy.HIERARCHY_NON_INDEPTH;
+ public static final int HIERARCHY_NON_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_NON_INDEPTH;
/**
* 1-indepth Hierarchy
*/
- public static final int HIERARCHY_1_INDEPTH =
- Constants.FrontendDvbtHierarchy.HIERARCHY_1_INDEPTH;
+ public static final int HIERARCHY_1_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_1_INDEPTH;
/**
* 2-indepth Hierarchy
*/
- public static final int HIERARCHY_2_INDEPTH =
- Constants.FrontendDvbtHierarchy.HIERARCHY_2_INDEPTH;
+ public static final int HIERARCHY_2_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_2_INDEPTH;
/**
* 4-indepth Hierarchy
*/
- public static final int HIERARCHY_4_INDEPTH =
- Constants.FrontendDvbtHierarchy.HIERARCHY_4_INDEPTH;
+ public static final int HIERARCHY_4_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_4_INDEPTH;
/** @hide */
@@ -264,48 +253,47 @@
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED =
- Constants.FrontendDvbtCoderate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendDvbtCoderate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically.
*/
- public static final int CODERATE_AUTO = Constants.FrontendDvbtCoderate.AUTO;
+ public static final int CODERATE_AUTO = FrontendDvbtCoderate.AUTO;
/**
* 1/2 code rate.
*/
- public static final int CODERATE_1_2 = Constants.FrontendDvbtCoderate.CODERATE_1_2;
+ public static final int CODERATE_1_2 = FrontendDvbtCoderate.CODERATE_1_2;
/**
* 2/3 code rate.
*/
- public static final int CODERATE_2_3 = Constants.FrontendDvbtCoderate.CODERATE_2_3;
+ public static final int CODERATE_2_3 = FrontendDvbtCoderate.CODERATE_2_3;
/**
* 3/4 code rate.
*/
- public static final int CODERATE_3_4 = Constants.FrontendDvbtCoderate.CODERATE_3_4;
+ public static final int CODERATE_3_4 = FrontendDvbtCoderate.CODERATE_3_4;
/**
* 5/6 code rate.
*/
- public static final int CODERATE_5_6 = Constants.FrontendDvbtCoderate.CODERATE_5_6;
+ public static final int CODERATE_5_6 = FrontendDvbtCoderate.CODERATE_5_6;
/**
* 7/8 code rate.
*/
- public static final int CODERATE_7_8 = Constants.FrontendDvbtCoderate.CODERATE_7_8;
+ public static final int CODERATE_7_8 = FrontendDvbtCoderate.CODERATE_7_8;
/**
* 4/5 code rate.
*/
- public static final int CODERATE_3_5 = Constants.FrontendDvbtCoderate.CODERATE_3_5;
+ public static final int CODERATE_3_5 = FrontendDvbtCoderate.CODERATE_3_5;
/**
* 4/5 code rate.
*/
- public static final int CODERATE_4_5 = Constants.FrontendDvbtCoderate.CODERATE_4_5;
+ public static final int CODERATE_4_5 = FrontendDvbtCoderate.CODERATE_4_5;
/**
* 6/7 code rate.
*/
- public static final int CODERATE_6_7 = Constants.FrontendDvbtCoderate.CODERATE_6_7;
+ public static final int CODERATE_6_7 = FrontendDvbtCoderate.CODERATE_6_7;
/**
* 8/9 code rate.
*/
- public static final int CODERATE_8_9 = Constants.FrontendDvbtCoderate.CODERATE_8_9;
+ public static final int CODERATE_8_9 = FrontendDvbtCoderate.CODERATE_8_9;
/** @hide */
@IntDef(flag = true,
@@ -323,46 +311,39 @@
* Guard Interval undefined.
*/
public static final int GUARD_INTERVAL_UNDEFINED =
- Constants.FrontendDvbtGuardInterval.UNDEFINED;
+ FrontendDvbtGuardInterval.UNDEFINED;
/**
* Hardware is able to detect and set Guard Interval automatically.
*/
- public static final int GUARD_INTERVAL_AUTO = Constants.FrontendDvbtGuardInterval.AUTO;
+ public static final int GUARD_INTERVAL_AUTO = FrontendDvbtGuardInterval.AUTO;
/**
* 1/32 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_32 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_32;
+ public static final int GUARD_INTERVAL_1_32 = FrontendDvbtGuardInterval.INTERVAL_1_32;
/**
* 1/16 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_16 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_16;
+ public static final int GUARD_INTERVAL_1_16 = FrontendDvbtGuardInterval.INTERVAL_1_16;
/**
* 1/8 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_8 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_8;
+ public static final int GUARD_INTERVAL_1_8 = FrontendDvbtGuardInterval.INTERVAL_1_8;
/**
* 1/4 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_4 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_4;
+ public static final int GUARD_INTERVAL_1_4 = FrontendDvbtGuardInterval.INTERVAL_1_4;
/**
* 1/128 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_128 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_128;
+ public static final int GUARD_INTERVAL_1_128 = FrontendDvbtGuardInterval.INTERVAL_1_128;
/**
* 19/128 Guard Interval.
*/
- public static final int GUARD_INTERVAL_19_128 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_19_128;
+ public static final int GUARD_INTERVAL_19_128 = FrontendDvbtGuardInterval.INTERVAL_19_128;
/**
* 19/256 Guard Interval.
*/
- public static final int GUARD_INTERVAL_19_256 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_19_256;
+ public static final int GUARD_INTERVAL_19_256 = FrontendDvbtGuardInterval.INTERVAL_19_256;
/** @hide */
@IntDef(flag = true,
@@ -375,15 +356,15 @@
/**
* Hardware is able to detect and set Standard automatically.
*/
- public static final int STANDARD_AUTO = Constants.FrontendDvbtStandard.AUTO;
+ public static final int STANDARD_AUTO = FrontendDvbtStandard.AUTO;
/**
* T standard.
*/
- public static final int STANDARD_T = Constants.FrontendDvbtStandard.T;
+ public static final int STANDARD_T = FrontendDvbtStandard.T;
/**
* T2 standard.
*/
- public static final int STANDARD_T2 = Constants.FrontendDvbtStandard.T2;
+ public static final int STANDARD_T2 = FrontendDvbtStandard.T2;
/** @hide */
@IntDef(prefix = "PLP_MODE_",
@@ -394,15 +375,15 @@
/**
* Physical Layer Pipe (PLP) Mode undefined.
*/
- public static final int PLP_MODE_UNDEFINED = Constants.FrontendDvbtPlpMode.UNDEFINED;
+ public static final int PLP_MODE_UNDEFINED = FrontendDvbtPlpMode.UNDEFINED;
/**
* Hardware is able to detect and set Physical Layer Pipe (PLP) Mode automatically.
*/
- public static final int PLP_MODE_AUTO = Constants.FrontendDvbtPlpMode.AUTO;
+ public static final int PLP_MODE_AUTO = FrontendDvbtPlpMode.AUTO;
/**
* Physical Layer Pipe (PLP) manual Mode.
*/
- public static final int PLP_MODE_MANUAL = Constants.FrontendDvbtPlpMode.MANUAL;
+ public static final int PLP_MODE_MANUAL = FrontendDvbtPlpMode.MANUAL;
private int mTransmissionMode;
private final int mBandwidth;
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
index 4bfe807..4a31686 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
@@ -20,7 +20,8 @@
import android.annotation.IntRange;
import android.annotation.LongDef;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendInnerFec;
+import android.hardware.tv.tuner.FrontendType;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.TunerVersionChecker;
@@ -44,47 +45,47 @@
/**
* Undefined frontend type.
*/
- public static final int TYPE_UNDEFINED = Constants.FrontendType.UNDEFINED;
+ public static final int TYPE_UNDEFINED = FrontendType.UNDEFINED;
/**
* Analog frontend type.
*/
- public static final int TYPE_ANALOG = Constants.FrontendType.ANALOG;
+ public static final int TYPE_ANALOG = FrontendType.ANALOG;
/**
* Advanced Television Systems Committee (ATSC) frontend type.
*/
- public static final int TYPE_ATSC = Constants.FrontendType.ATSC;
+ public static final int TYPE_ATSC = FrontendType.ATSC;
/**
* Advanced Television Systems Committee 3.0 (ATSC-3) frontend type.
*/
- public static final int TYPE_ATSC3 = Constants.FrontendType.ATSC3;
+ public static final int TYPE_ATSC3 = FrontendType.ATSC3;
/**
* Digital Video Broadcasting-Cable (DVB-C) frontend type.
*/
- public static final int TYPE_DVBC = Constants.FrontendType.DVBC;
+ public static final int TYPE_DVBC = FrontendType.DVBC;
/**
* Digital Video Broadcasting-Satellite (DVB-S) frontend type.
*/
- public static final int TYPE_DVBS = Constants.FrontendType.DVBS;
+ public static final int TYPE_DVBS = FrontendType.DVBS;
/**
* Digital Video Broadcasting-Terrestrial (DVB-T) frontend type.
*/
- public static final int TYPE_DVBT = Constants.FrontendType.DVBT;
+ public static final int TYPE_DVBT = FrontendType.DVBT;
/**
* Integrated Services Digital Broadcasting-Satellite (ISDB-S) frontend type.
*/
- public static final int TYPE_ISDBS = Constants.FrontendType.ISDBS;
+ public static final int TYPE_ISDBS = FrontendType.ISDBS;
/**
* Integrated Services Digital Broadcasting-Satellite 3 (ISDB-S3) frontend type.
*/
- public static final int TYPE_ISDBS3 = Constants.FrontendType.ISDBS3;
+ public static final int TYPE_ISDBS3 = FrontendType.ISDBS3;
/**
* Integrated Services Digital Broadcasting-Terrestrial (ISDB-T) frontend type.
*/
- public static final int TYPE_ISDBT = Constants.FrontendType.ISDBT;
+ public static final int TYPE_ISDBT = FrontendType.ISDBT;
/**
* Digital Terrestrial Multimedia Broadcast standard (DTMB) frontend type.
*/
- public static final int TYPE_DTMB = android.hardware.tv.tuner.V1_1.Constants.FrontendType.DTMB;
+ public static final int TYPE_DTMB = FrontendType.DTMB;
/** @hide */
@@ -101,151 +102,151 @@
/**
* FEC not defined.
*/
- public static final long FEC_UNDEFINED = Constants.FrontendInnerFec.FEC_UNDEFINED;
+ public static final long FEC_UNDEFINED = FrontendInnerFec.FEC_UNDEFINED;
/**
* hardware is able to detect and set FEC automatically.
*/
- public static final long FEC_AUTO = Constants.FrontendInnerFec.AUTO;
+ public static final long FEC_AUTO = FrontendInnerFec.AUTO;
/**
* 1/2 conv. code rate.
*/
- public static final long FEC_1_2 = Constants.FrontendInnerFec.FEC_1_2;
+ public static final long FEC_1_2 = FrontendInnerFec.FEC_1_2;
/**
* 1/3 conv. code rate.
*/
- public static final long FEC_1_3 = Constants.FrontendInnerFec.FEC_1_3;
+ public static final long FEC_1_3 = FrontendInnerFec.FEC_1_3;
/**
* 1/4 conv. code rate.
*/
- public static final long FEC_1_4 = Constants.FrontendInnerFec.FEC_1_4;
+ public static final long FEC_1_4 = FrontendInnerFec.FEC_1_4;
/**
* 1/5 conv. code rate.
*/
- public static final long FEC_1_5 = Constants.FrontendInnerFec.FEC_1_5;
+ public static final long FEC_1_5 = FrontendInnerFec.FEC_1_5;
/**
* 2/3 conv. code rate.
*/
- public static final long FEC_2_3 = Constants.FrontendInnerFec.FEC_2_3;
+ public static final long FEC_2_3 = FrontendInnerFec.FEC_2_3;
/**
* 2/5 conv. code rate.
*/
- public static final long FEC_2_5 = Constants.FrontendInnerFec.FEC_2_5;
+ public static final long FEC_2_5 = FrontendInnerFec.FEC_2_5;
/**
* 2/9 conv. code rate.
*/
- public static final long FEC_2_9 = Constants.FrontendInnerFec.FEC_2_9;
+ public static final long FEC_2_9 = FrontendInnerFec.FEC_2_9;
/**
* 3/4 conv. code rate.
*/
- public static final long FEC_3_4 = Constants.FrontendInnerFec.FEC_3_4;
+ public static final long FEC_3_4 = FrontendInnerFec.FEC_3_4;
/**
* 3/5 conv. code rate.
*/
- public static final long FEC_3_5 = Constants.FrontendInnerFec.FEC_3_5;
+ public static final long FEC_3_5 = FrontendInnerFec.FEC_3_5;
/**
* 4/5 conv. code rate.
*/
- public static final long FEC_4_5 = Constants.FrontendInnerFec.FEC_4_5;
+ public static final long FEC_4_5 = FrontendInnerFec.FEC_4_5;
/**
* 4/15 conv. code rate.
*/
- public static final long FEC_4_15 = Constants.FrontendInnerFec.FEC_4_15;
+ public static final long FEC_4_15 = FrontendInnerFec.FEC_4_15;
/**
* 5/6 conv. code rate.
*/
- public static final long FEC_5_6 = Constants.FrontendInnerFec.FEC_5_6;
+ public static final long FEC_5_6 = FrontendInnerFec.FEC_5_6;
/**
* 5/9 conv. code rate.
*/
- public static final long FEC_5_9 = Constants.FrontendInnerFec.FEC_5_9;
+ public static final long FEC_5_9 = FrontendInnerFec.FEC_5_9;
/**
* 6/7 conv. code rate.
*/
- public static final long FEC_6_7 = Constants.FrontendInnerFec.FEC_6_7;
+ public static final long FEC_6_7 = FrontendInnerFec.FEC_6_7;
/**
* 7/8 conv. code rate.
*/
- public static final long FEC_7_8 = Constants.FrontendInnerFec.FEC_7_8;
+ public static final long FEC_7_8 = FrontendInnerFec.FEC_7_8;
/**
* 7/9 conv. code rate.
*/
- public static final long FEC_7_9 = Constants.FrontendInnerFec.FEC_7_9;
+ public static final long FEC_7_9 = FrontendInnerFec.FEC_7_9;
/**
* 7/15 conv. code rate.
*/
- public static final long FEC_7_15 = Constants.FrontendInnerFec.FEC_7_15;
+ public static final long FEC_7_15 = FrontendInnerFec.FEC_7_15;
/**
* 8/9 conv. code rate.
*/
- public static final long FEC_8_9 = Constants.FrontendInnerFec.FEC_8_9;
+ public static final long FEC_8_9 = FrontendInnerFec.FEC_8_9;
/**
* 8/15 conv. code rate.
*/
- public static final long FEC_8_15 = Constants.FrontendInnerFec.FEC_8_15;
+ public static final long FEC_8_15 = FrontendInnerFec.FEC_8_15;
/**
* 9/10 conv. code rate.
*/
- public static final long FEC_9_10 = Constants.FrontendInnerFec.FEC_9_10;
+ public static final long FEC_9_10 = FrontendInnerFec.FEC_9_10;
/**
* 9/20 conv. code rate.
*/
- public static final long FEC_9_20 = Constants.FrontendInnerFec.FEC_9_20;
+ public static final long FEC_9_20 = FrontendInnerFec.FEC_9_20;
/**
* 11/15 conv. code rate.
*/
- public static final long FEC_11_15 = Constants.FrontendInnerFec.FEC_11_15;
+ public static final long FEC_11_15 = FrontendInnerFec.FEC_11_15;
/**
* 11/20 conv. code rate.
*/
- public static final long FEC_11_20 = Constants.FrontendInnerFec.FEC_11_20;
+ public static final long FEC_11_20 = FrontendInnerFec.FEC_11_20;
/**
* 11/45 conv. code rate.
*/
- public static final long FEC_11_45 = Constants.FrontendInnerFec.FEC_11_45;
+ public static final long FEC_11_45 = FrontendInnerFec.FEC_11_45;
/**
* 13/18 conv. code rate.
*/
- public static final long FEC_13_18 = Constants.FrontendInnerFec.FEC_13_18;
+ public static final long FEC_13_18 = FrontendInnerFec.FEC_13_18;
/**
* 13/45 conv. code rate.
*/
- public static final long FEC_13_45 = Constants.FrontendInnerFec.FEC_13_45;
+ public static final long FEC_13_45 = FrontendInnerFec.FEC_13_45;
/**
* 14/45 conv. code rate.
*/
- public static final long FEC_14_45 = Constants.FrontendInnerFec.FEC_14_45;
+ public static final long FEC_14_45 = FrontendInnerFec.FEC_14_45;
/**
* 23/36 conv. code rate.
*/
- public static final long FEC_23_36 = Constants.FrontendInnerFec.FEC_23_36;
+ public static final long FEC_23_36 = FrontendInnerFec.FEC_23_36;
/**
* 25/36 conv. code rate.
*/
- public static final long FEC_25_36 = Constants.FrontendInnerFec.FEC_25_36;
+ public static final long FEC_25_36 = FrontendInnerFec.FEC_25_36;
/**
* 26/45 conv. code rate.
*/
- public static final long FEC_26_45 = Constants.FrontendInnerFec.FEC_26_45;
+ public static final long FEC_26_45 = FrontendInnerFec.FEC_26_45;
/**
* 28/45 conv. code rate.
*/
- public static final long FEC_28_45 = Constants.FrontendInnerFec.FEC_28_45;
+ public static final long FEC_28_45 = FrontendInnerFec.FEC_28_45;
/**
* 29/45 conv. code rate.
*/
- public static final long FEC_29_45 = Constants.FrontendInnerFec.FEC_29_45;
+ public static final long FEC_29_45 = FrontendInnerFec.FEC_29_45;
/**
* 31/45 conv. code rate.
*/
- public static final long FEC_31_45 = Constants.FrontendInnerFec.FEC_31_45;
+ public static final long FEC_31_45 = FrontendInnerFec.FEC_31_45;
/**
* 32/45 conv. code rate.
*/
- public static final long FEC_32_45 = Constants.FrontendInnerFec.FEC_32_45;
+ public static final long FEC_32_45 = FrontendInnerFec.FEC_32_45;
/**
* 77/90 conv. code rate.
*/
- public static final long FEC_77_90 = Constants.FrontendInnerFec.FEC_77_90;
+ public static final long FEC_77_90 = FrontendInnerFec.FEC_77_90;
/** @hide */
@IntDef(prefix = "FRONTEND_SPECTRAL_INVERSION_",
@@ -258,17 +259,17 @@
* Spectral Inversion Type undefined.
*/
public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED =
- Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+ android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
/**
* Normal Spectral Inversion.
*/
public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL =
- Constants.FrontendDvbcSpectralInversion.NORMAL;
+ android.hardware.tv.tuner.FrontendSpectralInversion.NORMAL;
/**
* Inverted Spectral Inversion.
*/
public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED =
- Constants.FrontendDvbcSpectralInversion.INVERTED;
+ android.hardware.tv.tuner.FrontendSpectralInversion.INVERTED;
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index b82a5a9..36fd942 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -20,7 +20,6 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.Lnb;
import android.media.tv.tuner.TunerVersionChecker;
@@ -61,175 +60,188 @@
* Lock status for Demod.
*/
public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK =
- Constants.FrontendStatusType.DEMOD_LOCK;
+ android.hardware.tv.tuner.FrontendStatusType.DEMOD_LOCK;
/**
* Signal to Noise Ratio.
*/
- public static final int FRONTEND_STATUS_TYPE_SNR = Constants.FrontendStatusType.SNR;
+ public static final int FRONTEND_STATUS_TYPE_SNR =
+ android.hardware.tv.tuner.FrontendStatusType.SNR;
/**
* Bit Error Ratio.
*/
- public static final int FRONTEND_STATUS_TYPE_BER = Constants.FrontendStatusType.BER;
+ public static final int FRONTEND_STATUS_TYPE_BER =
+ android.hardware.tv.tuner.FrontendStatusType.BER;
/**
* Packages Error Ratio.
*/
- public static final int FRONTEND_STATUS_TYPE_PER = Constants.FrontendStatusType.PER;
+ public static final int FRONTEND_STATUS_TYPE_PER =
+ android.hardware.tv.tuner.FrontendStatusType.PER;
/**
* Bit Error Ratio before FEC.
*/
- public static final int FRONTEND_STATUS_TYPE_PRE_BER = Constants.FrontendStatusType.PRE_BER;
+ public static final int FRONTEND_STATUS_TYPE_PRE_BER =
+ android.hardware.tv.tuner.FrontendStatusType.PRE_BER;
/**
* Signal Quality (0..100). Good data over total data in percent can be
* used as a way to present Signal Quality.
*/
public static final int FRONTEND_STATUS_TYPE_SIGNAL_QUALITY =
- Constants.FrontendStatusType.SIGNAL_QUALITY;
+ android.hardware.tv.tuner.FrontendStatusType.SIGNAL_QUALITY;
/**
* Signal Strength.
*/
public static final int FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH =
- Constants.FrontendStatusType.SIGNAL_STRENGTH;
+ android.hardware.tv.tuner.FrontendStatusType.SIGNAL_STRENGTH;
/**
* Symbol Rate in symbols per second.
*/
public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE =
- Constants.FrontendStatusType.SYMBOL_RATE;
+ android.hardware.tv.tuner.FrontendStatusType.SYMBOL_RATE;
/**
* Forward Error Correction Type.
*/
- public static final int FRONTEND_STATUS_TYPE_FEC = Constants.FrontendStatusType.FEC;
+ public static final int FRONTEND_STATUS_TYPE_FEC =
+ android.hardware.tv.tuner.FrontendStatusType.FEC;
/**
* Modulation Type.
*/
public static final int FRONTEND_STATUS_TYPE_MODULATION =
- Constants.FrontendStatusType.MODULATION;
+ android.hardware.tv.tuner.FrontendStatusType.MODULATION;
/**
* Spectral Inversion Type.
*/
- public static final int FRONTEND_STATUS_TYPE_SPECTRAL = Constants.FrontendStatusType.SPECTRAL;
+ public static final int FRONTEND_STATUS_TYPE_SPECTRAL =
+ android.hardware.tv.tuner.FrontendStatusType.SPECTRAL;
/**
* LNB Voltage.
*/
public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE =
- Constants.FrontendStatusType.LNB_VOLTAGE;
+ android.hardware.tv.tuner.FrontendStatusType.LNB_VOLTAGE;
/**
* Physical Layer Pipe ID.
*/
- public static final int FRONTEND_STATUS_TYPE_PLP_ID = Constants.FrontendStatusType.PLP_ID;
+ public static final int FRONTEND_STATUS_TYPE_PLP_ID =
+ android.hardware.tv.tuner.FrontendStatusType.PLP_ID;
/**
* Status for Emergency Warning Broadcasting System.
*/
- public static final int FRONTEND_STATUS_TYPE_EWBS = Constants.FrontendStatusType.EWBS;
+ public static final int FRONTEND_STATUS_TYPE_EWBS =
+ android.hardware.tv.tuner.FrontendStatusType.EWBS;
/**
* Automatic Gain Control.
*/
- public static final int FRONTEND_STATUS_TYPE_AGC = Constants.FrontendStatusType.AGC;
+ public static final int FRONTEND_STATUS_TYPE_AGC =
+ android.hardware.tv.tuner.FrontendStatusType.AGC;
/**
* Low Noise Amplifier.
*/
- public static final int FRONTEND_STATUS_TYPE_LNA = Constants.FrontendStatusType.LNA;
+ public static final int FRONTEND_STATUS_TYPE_LNA =
+ android.hardware.tv.tuner.FrontendStatusType.LNA;
/**
* Error status by layer.
*/
public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR =
- Constants.FrontendStatusType.LAYER_ERROR;
+ android.hardware.tv.tuner.FrontendStatusType.LAYER_ERROR;
/**
* Modulation Error Ratio.
*/
- public static final int FRONTEND_STATUS_TYPE_MER = Constants.FrontendStatusType.MER;
+ public static final int FRONTEND_STATUS_TYPE_MER =
+ android.hardware.tv.tuner.FrontendStatusType.MER;
/**
* Difference between tuning frequency and actual locked frequency.
*/
public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET =
- Constants.FrontendStatusType.FREQ_OFFSET;
+ android.hardware.tv.tuner.FrontendStatusType.FREQ_OFFSET;
/**
* Hierarchy for DVBT.
*/
- public static final int FRONTEND_STATUS_TYPE_HIERARCHY = Constants.FrontendStatusType.HIERARCHY;
+ public static final int FRONTEND_STATUS_TYPE_HIERARCHY =
+ android.hardware.tv.tuner.FrontendStatusType.HIERARCHY;
/**
* Lock status for RF.
*/
- public static final int FRONTEND_STATUS_TYPE_RF_LOCK = Constants.FrontendStatusType.RF_LOCK;
+ public static final int FRONTEND_STATUS_TYPE_RF_LOCK =
+ android.hardware.tv.tuner.FrontendStatusType.RF_LOCK;
/**
* PLP information in a frequency band for ATSC-3.0 frontend.
*/
public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO =
- Constants.FrontendStatusType.ATSC3_PLP_INFO;
+ android.hardware.tv.tuner.FrontendStatusType.ATSC3_PLP_INFO;
/**
* BERS Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_BERS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BERS;
+ android.hardware.tv.tuner.FrontendStatusType.BERS;
/**
* Coderate Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_CODERATES =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.CODERATES;
+ android.hardware.tv.tuner.FrontendStatusType.CODERATES;
/**
* Bandwidth Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_BANDWIDTH =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BANDWIDTH;
+ android.hardware.tv.tuner.FrontendStatusType.BANDWIDTH;
/**
* Guard Interval Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.GUARD_INTERVAL;
+ android.hardware.tv.tuner.FrontendStatusType.GUARD_INTERVAL;
/**
* Transmission Mode Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TRANSMISSION_MODE;
+ android.hardware.tv.tuner.FrontendStatusType.TRANSMISSION_MODE;
/**
* UEC Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_UEC =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.UEC;
+ android.hardware.tv.tuner.FrontendStatusType.UEC;
/**
* T2 System Id Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.T2_SYSTEM_ID;
+ android.hardware.tv.tuner.FrontendStatusType.T2_SYSTEM_ID;
/**
* Interleavings Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.INTERLEAVINGS;
+ android.hardware.tv.tuner.FrontendStatusType.INTERLEAVINGS;
/**
* ISDBT Segments Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.ISDBT_SEGMENTS;
+ android.hardware.tv.tuner.FrontendStatusType.ISDBT_SEGMENTS;
/**
* TS Data Rates Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TS_DATA_RATES;
+ android.hardware.tv.tuner.FrontendStatusType.TS_DATA_RATES;
/**
* Extended Modulations Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.MODULATIONS;
+ android.hardware.tv.tuner.FrontendStatusType.MODULATIONS;
/**
* Roll Off Type status of the frontend. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_ROLL_OFF =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.ROLL_OFF;
+ android.hardware.tv.tuner.FrontendStatusType.ROLL_OFF;
/**
* If the frontend currently supports MISO or not. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_IS_MISO_ENABLED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_MISO;
+ android.hardware.tv.tuner.FrontendStatusType.IS_MISO;
/**
* If the frontend code rate is linear or not. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_IS_LINEAR =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_LINEAR;
+ android.hardware.tv.tuner.FrontendStatusType.IS_LINEAR;
/**
* If short frames is enabled or not. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES_ENABLED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_SHORT_FRAMES;
+ android.hardware.tv.tuner.FrontendStatusType.IS_SHORT_FRAMES;
/** @hide */
@IntDef(value = {
diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
index 02cdb96..14b0b02 100644
--- a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
@@ -20,7 +20,9 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbs3Coderate;
+import android.hardware.tv.tuner.FrontendIsdbs3Modulation;
+import android.hardware.tv.tuner.FrontendIsdbs3Rolloff;
import android.media.tv.tuner.Tuner;
import java.lang.annotation.Retention;
@@ -45,31 +47,31 @@
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbs3Modulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendIsdbs3Modulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically.
*/
- public static final int MODULATION_AUTO = Constants.FrontendIsdbs3Modulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendIsdbs3Modulation.AUTO;
/**
* BPSK Modulation.
*/
- public static final int MODULATION_MOD_BPSK = Constants.FrontendIsdbs3Modulation.MOD_BPSK;
+ public static final int MODULATION_MOD_BPSK = FrontendIsdbs3Modulation.MOD_BPSK;
/**
* QPSK Modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbs3Modulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendIsdbs3Modulation.MOD_QPSK;
/**
* 8PSK Modulation.
*/
- public static final int MODULATION_MOD_8PSK = Constants.FrontendIsdbs3Modulation.MOD_8PSK;
+ public static final int MODULATION_MOD_8PSK = FrontendIsdbs3Modulation.MOD_8PSK;
/**
* 16APSK Modulation.
*/
- public static final int MODULATION_MOD_16APSK = Constants.FrontendIsdbs3Modulation.MOD_16APSK;
+ public static final int MODULATION_MOD_16APSK = FrontendIsdbs3Modulation.MOD_16APSK;
/**
* 32APSK Modulation.
*/
- public static final int MODULATION_MOD_32APSK = Constants.FrontendIsdbs3Modulation.MOD_32APSK;
+ public static final int MODULATION_MOD_32APSK = FrontendIsdbs3Modulation.MOD_32APSK;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -83,55 +85,55 @@
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED = Constants.FrontendIsdbs3Coderate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendIsdbs3Coderate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically.
*/
- public static final int CODERATE_AUTO = Constants.FrontendIsdbs3Coderate.AUTO;
+ public static final int CODERATE_AUTO = FrontendIsdbs3Coderate.AUTO;
/**
* 1/3 code rate.
*/
- public static final int CODERATE_1_3 = Constants.FrontendIsdbs3Coderate.CODERATE_1_3;
+ public static final int CODERATE_1_3 = FrontendIsdbs3Coderate.CODERATE_1_3;
/**
* 2/5 code rate.
*/
- public static final int CODERATE_2_5 = Constants.FrontendIsdbs3Coderate.CODERATE_2_5;
+ public static final int CODERATE_2_5 = FrontendIsdbs3Coderate.CODERATE_2_5;
/**
* 1/2 code rate.
*/
- public static final int CODERATE_1_2 = Constants.FrontendIsdbs3Coderate.CODERATE_1_2;
+ public static final int CODERATE_1_2 = FrontendIsdbs3Coderate.CODERATE_1_2;
/**
* 3/5 code rate.
*/
- public static final int CODERATE_3_5 = Constants.FrontendIsdbs3Coderate.CODERATE_3_5;
+ public static final int CODERATE_3_5 = FrontendIsdbs3Coderate.CODERATE_3_5;
/**
* 2/3 code rate.
*/
- public static final int CODERATE_2_3 = Constants.FrontendIsdbs3Coderate.CODERATE_2_3;
+ public static final int CODERATE_2_3 = FrontendIsdbs3Coderate.CODERATE_2_3;
/**
* 3/4 code rate.
*/
- public static final int CODERATE_3_4 = Constants.FrontendIsdbs3Coderate.CODERATE_3_4;
+ public static final int CODERATE_3_4 = FrontendIsdbs3Coderate.CODERATE_3_4;
/**
* 7/9 code rate.
*/
- public static final int CODERATE_7_9 = Constants.FrontendIsdbs3Coderate.CODERATE_7_9;
+ public static final int CODERATE_7_9 = FrontendIsdbs3Coderate.CODERATE_7_9;
/**
* 4/5 code rate.
*/
- public static final int CODERATE_4_5 = Constants.FrontendIsdbs3Coderate.CODERATE_4_5;
+ public static final int CODERATE_4_5 = FrontendIsdbs3Coderate.CODERATE_4_5;
/**
* 5/6 code rate.
*/
- public static final int CODERATE_5_6 = Constants.FrontendIsdbs3Coderate.CODERATE_5_6;
+ public static final int CODERATE_5_6 = FrontendIsdbs3Coderate.CODERATE_5_6;
/**
* 7/8 code rate.
*/
- public static final int CODERATE_7_8 = Constants.FrontendIsdbs3Coderate.CODERATE_7_8;
+ public static final int CODERATE_7_8 = FrontendIsdbs3Coderate.CODERATE_7_8;
/**
* 9/10 code rate.
*/
- public static final int CODERATE_9_10 = Constants.FrontendIsdbs3Coderate.CODERATE_9_10;
+ public static final int CODERATE_9_10 = FrontendIsdbs3Coderate.CODERATE_9_10;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -142,11 +144,11 @@
/**
* Rolloff type undefined.
*/
- public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbs3Rolloff.UNDEFINED;
+ public static final int ROLLOFF_UNDEFINED = FrontendIsdbs3Rolloff.UNDEFINED;
/**
* 0,03 Rolloff.
*/
- public static final int ROLLOFF_0_03 = Constants.FrontendIsdbs3Rolloff.ROLLOFF_0_03;
+ public static final int ROLLOFF_0_03 = FrontendIsdbs3Rolloff.ROLLOFF_0_03;
private final int mStreamId;
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
index 3cc1aab..aab6408 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
@@ -20,7 +20,10 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbsCoderate;
+import android.hardware.tv.tuner.FrontendIsdbsModulation;
+import android.hardware.tv.tuner.FrontendIsdbsRolloff;
+import android.hardware.tv.tuner.FrontendIsdbsStreamIdType;
import android.media.tv.tuner.Tuner;
import java.lang.annotation.Retention;
@@ -42,12 +45,12 @@
/**
* Uses stream ID.
*/
- public static final int STREAM_ID_TYPE_ID = Constants.FrontendIsdbsStreamIdType.STREAM_ID;
+ public static final int STREAM_ID_TYPE_ID = FrontendIsdbsStreamIdType.STREAM_ID;
/**
* Uses relative number.
*/
public static final int STREAM_ID_TYPE_RELATIVE_NUMBER =
- Constants.FrontendIsdbsStreamIdType.RELATIVE_STREAM_NUMBER;
+ FrontendIsdbsStreamIdType.RELATIVE_STREAM_NUMBER;
/** @hide */
@@ -61,23 +64,23 @@
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbsModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendIsdbsModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendIsdbsModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendIsdbsModulation.AUTO;
/**
* BPSK Modulation.
*/
- public static final int MODULATION_MOD_BPSK = Constants.FrontendIsdbsModulation.MOD_BPSK;
+ public static final int MODULATION_MOD_BPSK = FrontendIsdbsModulation.MOD_BPSK;
/**
* QPSK Modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbsModulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendIsdbsModulation.MOD_QPSK;
/**
* TC8PSK Modulation.
*/
- public static final int MODULATION_MOD_TC8PSK = Constants.FrontendIsdbsModulation.MOD_TC8PSK;
+ public static final int MODULATION_MOD_TC8PSK = FrontendIsdbsModulation.MOD_TC8PSK;
/** @hide */
@@ -91,31 +94,31 @@
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED = Constants.FrontendIsdbsCoderate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendIsdbsCoderate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically.
*/
- public static final int CODERATE_AUTO = Constants.FrontendIsdbsCoderate.AUTO;
+ public static final int CODERATE_AUTO = FrontendIsdbsCoderate.AUTO;
/**
* 1/2 code rate.
*/
- public static final int CODERATE_1_2 = Constants.FrontendIsdbsCoderate.CODERATE_1_2;
+ public static final int CODERATE_1_2 = FrontendIsdbsCoderate.CODERATE_1_2;
/**
* 2/3 code rate.
*/
- public static final int CODERATE_2_3 = Constants.FrontendIsdbsCoderate.CODERATE_2_3;
+ public static final int CODERATE_2_3 = FrontendIsdbsCoderate.CODERATE_2_3;
/**
* 3/4 code rate.
*/
- public static final int CODERATE_3_4 = Constants.FrontendIsdbsCoderate.CODERATE_3_4;
+ public static final int CODERATE_3_4 = FrontendIsdbsCoderate.CODERATE_3_4;
/**
* 5/6 code rate.
*/
- public static final int CODERATE_5_6 = Constants.FrontendIsdbsCoderate.CODERATE_5_6;
+ public static final int CODERATE_5_6 = FrontendIsdbsCoderate.CODERATE_5_6;
/**
* 7/8 code rate.
*/
- public static final int CODERATE_7_8 = Constants.FrontendIsdbsCoderate.CODERATE_7_8;
+ public static final int CODERATE_7_8 = FrontendIsdbsCoderate.CODERATE_7_8;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -126,11 +129,11 @@
/**
* Rolloff type undefined.
*/
- public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbsRolloff.UNDEFINED;
+ public static final int ROLLOFF_UNDEFINED = FrontendIsdbsRolloff.UNDEFINED;
/**
* 0,35 rolloff.
*/
- public static final int ROLLOFF_0_35 = Constants.FrontendIsdbsRolloff.ROLLOFF_0_35;
+ public static final int ROLLOFF_0_35 = FrontendIsdbsRolloff.ROLLOFF_0_35;
private final int mStreamId;
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
index 6a14d08..de2476a 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
@@ -20,7 +20,9 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbtBandwidth;
+import android.hardware.tv.tuner.FrontendIsdbtMode;
+import android.hardware.tv.tuner.FrontendIsdbtModulation;
import android.media.tv.tuner.frontend.DvbtFrontendSettings.CodeRate;
import java.lang.annotation.Retention;
@@ -44,27 +46,27 @@
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbtModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendIsdbtModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendIsdbtModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendIsdbtModulation.AUTO;
/**
* DQPSK Modulation.
*/
- public static final int MODULATION_MOD_DQPSK = Constants.FrontendIsdbtModulation.MOD_DQPSK;
+ public static final int MODULATION_MOD_DQPSK = FrontendIsdbtModulation.MOD_DQPSK;
/**
* QPSK Modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbtModulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendIsdbtModulation.MOD_QPSK;
/**
* 16QAM Modulation.
*/
- public static final int MODULATION_MOD_16QAM = Constants.FrontendIsdbtModulation.MOD_16QAM;
+ public static final int MODULATION_MOD_16QAM = FrontendIsdbtModulation.MOD_16QAM;
/**
* 64QAM Modulation.
*/
- public static final int MODULATION_MOD_64QAM = Constants.FrontendIsdbtModulation.MOD_64QAM;
+ public static final int MODULATION_MOD_64QAM = FrontendIsdbtModulation.MOD_64QAM;
/** @hide */
@@ -77,23 +79,23 @@
/**
* Mode undefined.
*/
- public static final int MODE_UNDEFINED = Constants.FrontendIsdbtMode.UNDEFINED;
+ public static final int MODE_UNDEFINED = FrontendIsdbtMode.UNDEFINED;
/**
* Hardware is able to detect and set Mode automatically.
*/
- public static final int MODE_AUTO = Constants.FrontendIsdbtMode.AUTO;
+ public static final int MODE_AUTO = FrontendIsdbtMode.AUTO;
/**
* Mode 1
*/
- public static final int MODE_1 = Constants.FrontendIsdbtMode.MODE_1;
+ public static final int MODE_1 = FrontendIsdbtMode.MODE_1;
/**
* Mode 2
*/
- public static final int MODE_2 = Constants.FrontendIsdbtMode.MODE_2;
+ public static final int MODE_2 = FrontendIsdbtMode.MODE_2;
/**
* Mode 3
*/
- public static final int MODE_3 = Constants.FrontendIsdbtMode.MODE_3;
+ public static final int MODE_3 = FrontendIsdbtMode.MODE_3;
/** @hide */
@@ -107,23 +109,23 @@
/**
* Bandwidth undefined.
*/
- public static final int BANDWIDTH_UNDEFINED = Constants.FrontendIsdbtBandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendIsdbtBandwidth.UNDEFINED;
/**
* Hardware is able to detect and set Bandwidth automatically.
*/
- public static final int BANDWIDTH_AUTO = Constants.FrontendIsdbtBandwidth.AUTO;
+ public static final int BANDWIDTH_AUTO = FrontendIsdbtBandwidth.AUTO;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_8MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_8MHZ = FrontendIsdbtBandwidth.BANDWIDTH_8MHZ;
/**
* 7 MHz bandwidth.
*/
- public static final int BANDWIDTH_7MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_7MHZ;
+ public static final int BANDWIDTH_7MHZ = FrontendIsdbtBandwidth.BANDWIDTH_7MHZ;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_6MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_6MHZ = FrontendIsdbtBandwidth.BANDWIDTH_6MHZ;
private final int mModulation;
private final int mBandwidth;
diff --git a/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java b/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
index 5cf0d31..3b5419e 100644
--- a/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
+++ b/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendEventType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -37,11 +37,11 @@
@interface TuneEvent {}
/** The frontend has locked to the signal specified by the tune method. */
- int SIGNAL_LOCKED = Constants.FrontendEventType.LOCKED;
+ int SIGNAL_LOCKED = FrontendEventType.LOCKED;
/** The frontend is unable to lock to the signal specified by the tune method. */
- int SIGNAL_NO_SIGNAL = Constants.FrontendEventType.NO_SIGNAL;
+ int SIGNAL_NO_SIGNAL = FrontendEventType.NO_SIGNAL;
/** The frontend has lost the lock to the signal specified by the tune method. */
- int SIGNAL_LOST_LOCK = Constants.FrontendEventType.LOST_LOCK;
+ int SIGNAL_LOST_LOCK = FrontendEventType.LOST_LOCK;
/** Tune Event from the frontend */
void onTuneEvent(@TuneEvent int tuneEvent);
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index bc73f6a..c775b6f 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -183,8 +183,8 @@
"libmedia",
"libnativehelper",
"libutils",
- "tv_tuner_aidl_interface-ndk_platform",
- "tv_tuner_resource_manager_aidl_interface-ndk_platform",
+ "tv_tuner_aidl_interface-ndk",
+ "tv_tuner_resource_manager_aidl_interface-ndk",
],
static_libs: [
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index e4f3f33..698fb5a5 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1245,7 +1245,8 @@
return NULL;
}
- sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject);
+ sp<FrontendClientCallbackImpl> feClientCb =
+ new FrontendClientCallbackImpl(env->NewWeakGlobalRef(mObject));
mFeClient->setCallback(feClientCb);
// TODO: add more fields to frontend
return env->NewObject(
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml
new file mode 100644
index 0000000..064f14a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Ayarlar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..d51823f
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Podešavanja"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml
new file mode 100644
index 0000000..df46ee7
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Настройки"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml
new file mode 100644
index 0000000..442217a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Postavke"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..b048293
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..b048293
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..b048293
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..b048293
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..d5c868b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml
new file mode 100644
index 0000000..64dddc9
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Ajustes"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml
new file mode 100644
index 0000000..76a8bd7
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"تنظیمات"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml
new file mode 100644
index 0000000..442217a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Postavke"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml
new file mode 100644
index 0000000..bdab372
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Beállítások"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml
new file mode 100644
index 0000000..d91474a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Կարգավորումներ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml
new file mode 100644
index 0000000..1c0204d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Impostazioni"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml
new file mode 100644
index 0000000..28ff3e72
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"הגדרות"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml
new file mode 100644
index 0000000..b8acb7b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml
new file mode 100644
index 0000000..671fc1c
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"პარამეტრები"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml
new file mode 100644
index 0000000..bcd6784b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Параметрлер"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml
new file mode 100644
index 0000000..df2c7d0
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ការកំណត់"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml
new file mode 100644
index 0000000..8a54318
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"설정"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
new file mode 100644
index 0000000..f4a893a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Жөндөөлөр"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml
new file mode 100644
index 0000000..2a91bc3
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ການຕັ້ງຄ່າ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml
new file mode 100644
index 0000000..194aa02
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Тохиргоо"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml
new file mode 100644
index 0000000..9a7365d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Instellingen"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..87dbe7d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Configurações"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..5ac7278
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Definições"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml
new file mode 100644
index 0000000..87dbe7d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Configurações"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml
new file mode 100644
index 0000000..10f8475
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"සැකසීම්"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml
new file mode 100644
index 0000000..41b33fe
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Nastavitve"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml
new file mode 100644
index 0000000..1478a00
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Подешавања"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml
new file mode 100644
index 0000000..ef54206
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Inställningar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml
new file mode 100644
index 0000000..d5dbf19
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Mipangilio"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml
new file mode 100644
index 0000000..f923a18
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Mga Setting"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml
new file mode 100644
index 0000000..8f03a19
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Налаштування"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml
new file mode 100644
index 0000000..e8fb658
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Sozlamalar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml
new file mode 100644
index 0000000..ab7136b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Cài đặt"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..b8acb7b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..b8acb7b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml
new file mode 100644
index 0000000..bb87ec2
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Amasethingi"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 0fd9ae5..5c9a3e0 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"ওয়্যারলেস ডিসপ্লে সার্টিফিকেশন"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"ওয়াই-ফাই ভারবোস লগিং চালু করুন"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"ওয়াই-ফাই স্ক্যান থ্রোটলিং"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"অল্প সময় ওয়াই-ফাই নেটওয়ার্কে যুক্ত থাকে এমন MAC অ্যাড্রেসের র্যান্ডমাইজেশন"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখুন"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ব্যাটারির খরচ কমায় এবং নেটওয়ার্কের পারফর্ম্যান্স উন্নত করে"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"এই মোডটি চালু থাকলে, MAC অ্যাড্রেসের র্যান্ডমাইজেশনের সুবিধা চালু আছে এমন কোনও নেটওয়ার্কে প্রত্যেকবার কানেক্ট করার সময় ডিভাইসের MAC অ্যাড্রেস পরিবর্তিত হতে পারে।"</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"মিটার্ড"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"পরিমাপ করা নয়"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"লগার বাফারের আকারগুলি"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 3abd211..a225b74 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -284,7 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"Afficher les options pour la certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Détailler les infos Wi-Fi, afficher par RSSI de SSID dans l\'outil de sélection Wi-Fi"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Réduit la décharge de la batterie et améliore les performances du réseau"</string>
- <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quand ce mode est activé, l\'adresse MAC de cet appareil peut changer chaque fois qu\'il se connecte à un réseau Wi-Fi où le changement aléatoire d\'adresse MAC est activé."</string>
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quand ce mode est activé, l\'adresse MAC de cet appareil peut changer chaque fois qu\'il se connecte à un réseau où le changement aléatoire d\'adresse MAC est activé."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"Facturé à l\'usage"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"Non facturé à l\'usage"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"Tailles des tampons de l\'enregistreur"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 9fc70cf..eedadc9 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ ચાલુ કરો"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"વાઇ-ફાઇ સ્કૅનની ક્ષમતા મર્યાદિત કરવી"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"વાઇ-ફાઇ માટે સતત બદલાતું MAC રેન્ડમાઇઝેશન"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"નામ વિનાના બ્લૂટૂથ ડિવાઇસ બતાવો"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"બૅટરીનો ચાર્જ ઝડપથી ઓછો થવાનું ટાળે છે અને નેટવર્કના કાર્યપ્રદર્શનમાં સુધારો કરે છે"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"આ મોડ ચાલુ કરેલો હોય ત્યારે MAC રેન્ડમાઇઝેશન ચાલુ કરેલું હોય તેવા નેટવર્ક સાથે આ ડિવાઇસ કનેક્ટ થશે, ત્યારે દર વખતે તેનું MAC ઍડ્રેસ બદલાય તેવું બની શકે છે."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"મીટર કરેલું"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"મીટર ન કરેલ"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"લોગર બફર કદ"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index fba3aeb..67247ea 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -252,7 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"אישור של תצוגת Wi-Fi"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"הפעלת רישום מפורט של Wi‑Fi ביומן"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"ויסות סריקה לנקודות Wi-Fi"</string>
- <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"רנדומיזציה של כתובות MAC בלי חיבור יציב ל-Wi-Fi"</string>
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"רנדומיזציה של כתובות MAC משתנות ברשתות Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"חבילת הגלישה פעילה תמיד"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"הצגת מכשירי Bluetooth ללא שמות"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 99fd1d3..3af8728 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"ವೈರ್ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣ"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi‑Fi ವೆರ್ಬೋಸ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"ವೈ-ಫೈ ಸ್ಕ್ಯಾನ್ ನಿರ್ಬಂಧಿಸಲಾಗುತ್ತಿದೆ"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"ವೈ-ಫೈ ನಿರಂತರವಲ್ಲದ MAC ಯಾದೃಚ್ಛಿಕರಣ"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"ಟೆಥರಿಂಗ್ಗಾಗಿ ಹಾರ್ಡ್ವೇರ್ ವೇಗವರ್ಧನೆ"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"ಹೆಸರುಗಳಿಲ್ಲದ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ತೋರಿಸಿ"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"ವೈರ್ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ಬ್ಯಾಟರಿ ಹೆಚ್ಚು ಬಾಳಿಕೆ ಬರುವಂತೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ನೆಟ್ವರ್ಕ್ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಸುಧಾರಿಸುತ್ತದೆ"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"ಈ ಮೋಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ, MAC ಯಾದೃಚ್ಛಿಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿದಾಗ ಈ ಸಾಧನದ MAC ವಿಳಾಸವು ಪ್ರತಿ ಬಾರಿಯೂ ಬದಲಾಗಬಹುದು."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"ಮೀಟರ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"ಮೀಟರ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 0b0a4a6..95e6f63 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"वायरलेस डिस्प्ले प्रमाणीकरण"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"वाय-फाय व्हर्बोझ लॉगिंग सुरू करा"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"वाय-फाय स्कॅन थ्रॉटलिंग"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"वाय-फायचे सातत्याने न होणारे MAC रँडमायझेशन"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"मोबाइल डेटा नेहमी सक्रिय"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"टेदरिंग हार्डवेअर अॅक्सिलरेशन"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"नावांशिवाय ब्लूटूथ डिव्हाइस दाखवा"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"वाय-फाय लॉगिंग स्तर वाढवा, वाय-फाय सिलेक्टरमध्ये प्रति SSID RSSI दर्शवा"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"बॅटरी जलदरीतीने संपण्यापासून रोखते आणि नेटवर्क परफॉर्मन्समध्ये सुधारणा करते"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"हा मोड सुरू केलेला असले तेव्हा, हे डिव्हाइस MAC रँडमायझेशन सुरू केलेल्या नेटवर्कशी कनेक्ट होताना प्रत्येक वेळी त्याचा MAC अॅड्रेस बदलू शकतो."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"मीटरने मोजलेले"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"मीटरने न मोजलेले"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"लॉगर बफर आकार"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index b004082..c088d85 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"Certifikimi i ekranit pa tel"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Aktivizo hyrjen Wi-Fi Verbose"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"Përshpejtimi i skanimit të Wi‑Fi"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Renditje e rastësishme jo e përhershme e MAC për Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"Të dhënat celulare gjithmonë aktive"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Përshpejtimi i harduerit për ndarjen e lidhjes (internet)"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Shfaq pajisjet me Bluetooth pa emra"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"Shfaq opsionet për certifikimin e ekranit pa tel"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Zvogëlon shkarkimin e baterisë dhe përmirëson cilësinë e funksionimit të rrjetit"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Kur ky modalitet është i aktivizuar, adresa MAC e kësaj pajisjeje mund të ndryshojë çdo herë që lidhet me një rrjet që ka të aktivizuar renditjen e rastësishme të adresave MAC."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"Me matje"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"Pa matje"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"Madhësitë e regjistruesit"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 71e4fe2..db8edf7 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -489,7 +489,7 @@
<string name="active_input_method_subtypes" msgid="4232680535471633046">"సక్రియ ఇన్పుట్ పద్ధతులు"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"సిస్టమ్ భాషలను ఉపయోగించు"</string>
<string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> యొక్క సెట్టింగ్లను తెరవడం విఫలమైంది"</string>
- <string name="ime_security_warning" msgid="6547562217880551450">"ఈ ఇన్పుట్ పద్ధతి మీరు టైప్ చేసే మొత్తం వచనాన్ని అలాగే పాస్వర్డ్లు మరియు క్రెడిట్ కార్డు నంబర్ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> అనువర్తనంలో అందించబడుతుంది. ఈ ఇన్పుట్ పద్ధతిని ఉపయోగించాలా?"</string>
+ <string name="ime_security_warning" msgid="6547562217880551450">"ఈ ఇన్పుట్ పద్ధతి మీరు టైప్ చేసే మొత్తం వచనాన్ని అలాగే పాస్వర్డ్లు మరియు క్రెడిట్ కార్డు నంబర్ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> యాప్లో అందించబడుతుంది. ఈ ఇన్పుట్ పద్ధతిని ఉపయోగించాలా?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"గమనిక: రీబూట్ చేసాక, మీరు మీ ఫోన్ను అన్లాక్ చేసే వరకు ఈ యాప్ ప్రారంభం కాదు"</string>
<string name="ims_reg_title" msgid="8197592958123671062">"IMS నమోదు స్థితి"</string>
<string name="ims_reg_status_registered" msgid="884916398194885457">"నమోదు చేయబడింది"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 79446e4..ed8d524 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -44,6 +44,8 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.RequiresApi;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -56,6 +58,7 @@
/**
* InfoMediaManager provide interface to get InfoMediaDevice list.
*/
+@RequiresApi(Build.VERSION_CODES.R)
public class InfoMediaManager extends MediaManager {
private static final String TAG = "InfoMediaManager";
@@ -145,9 +148,16 @@
}
private RoutingSessionInfo getRoutingSessionInfo() {
- final List<RoutingSessionInfo> sessionInfos =
- mRouterManager.getRoutingSessions(mPackageName);
+ return getRoutingSessionInfo(mPackageName);
+ }
+ private RoutingSessionInfo getRoutingSessionInfo(String packageName) {
+ final List<RoutingSessionInfo> sessionInfos =
+ mRouterManager.getRoutingSessions(packageName);
+
+ if (sessionInfos == null || sessionInfos.isEmpty()) {
+ return null;
+ }
return sessionInfos.get(sessionInfos.size() - 1);
}
@@ -367,33 +377,13 @@
}
boolean shouldDisableMediaOutput(String packageName) {
- boolean shouldDisableMediaOutput = false;
if (TextUtils.isEmpty(packageName)) {
Log.w(TAG, "shouldDisableMediaOutput() package name is null or empty!");
- return false;
+ return true;
}
- final List<MediaRoute2Info> infos = mRouterManager.getTransferableRoutes(packageName);
- if (infos.size() == 1) {
- final MediaRoute2Info info = infos.get(0);
- final int deviceType = info.getType();
- switch (deviceType) {
- case TYPE_UNKNOWN:
- case TYPE_REMOTE_TV:
- case TYPE_REMOTE_SPEAKER:
- case TYPE_GROUP:
- shouldDisableMediaOutput = true;
- break;
- default:
- shouldDisableMediaOutput = false;
- break;
- }
- }
- if (DEBUG) {
- Log.d(TAG, "shouldDisableMediaOutput() MediaRoute2Info size : " + infos.size()
- + ", package name : " + packageName + ", shouldDisableMediaOutput : "
- + shouldDisableMediaOutput);
- }
- return shouldDisableMediaOutput;
+
+ // Disable when there is no transferable route
+ return mRouterManager.getTransferableRoutes(packageName).isEmpty();
}
@TargetApi(Build.VERSION_CODES.R)
@@ -456,7 +446,7 @@
}
private void buildAvailableRoutes() {
- for (MediaRoute2Info route : mRouterManager.getTransferableRoutes(mPackageName)) {
+ for (MediaRoute2Info route : getAvailableRoutes(mPackageName)) {
if (DEBUG) {
Log.d(TAG, "buildAvailableRoutes() route : " + route.getName() + ", volume : "
+ route.getVolume() + ", type : " + route.getType());
@@ -465,6 +455,29 @@
}
}
+ private List<MediaRoute2Info> getAvailableRoutes(String packageName) {
+ final List<MediaRoute2Info> infos = new ArrayList<>();
+ RoutingSessionInfo routingSessionInfo = getRoutingSessionInfo(packageName);
+ if (routingSessionInfo != null) {
+ infos.addAll(mRouterManager.getSelectedRoutes(routingSessionInfo));
+ }
+ final List<MediaRoute2Info> transferableRoutes =
+ mRouterManager.getTransferableRoutes(packageName);
+ for (MediaRoute2Info transferableRoute : transferableRoutes) {
+ boolean alreadyAdded = false;
+ for (MediaRoute2Info mediaRoute2Info : infos) {
+ if (TextUtils.equals(transferableRoute.getId(), mediaRoute2Info.getId())) {
+ alreadyAdded = true;
+ break;
+ }
+ }
+ if (!alreadyAdded) {
+ infos.add(transferableRoute);
+ }
+ }
+ return infos;
+ }
+
@VisibleForTesting
void addMediaDevice(MediaRoute2Info route) {
final int deviceType = route.getType();
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index a8da2c0..22001c9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -22,11 +22,13 @@
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.media.RoutingSessionInfo;
+import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.A2dpProfile;
@@ -49,6 +51,7 @@
/**
* LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
*/
+@RequiresApi(Build.VERSION_CODES.R)
public class LocalMediaManager implements BluetoothCallback {
private static final Comparator<MediaDevice> COMPARATOR = Comparator.naturalOrder();
private static final String TAG = "LocalMediaManager";
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 294399e..6bb125b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3588,7 +3588,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 204;
+ private static final int SETTINGS_VERSION = 205;
private final int mUserId;
@@ -5399,6 +5399,44 @@
currentVersion = 204;
}
+ if (currentVersion == 204) {
+ // Version 204: Replace 'wifi' or 'cell' tiles with 'internet' if existed.
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final Setting currentValue = secureSettings.getSettingLocked(Secure.QS_TILES);
+ if (!currentValue.isNull()) {
+ String tileList = currentValue.getValue();
+ String[] tileSplit = tileList.split(",");
+ final ArrayList<String> tiles = new ArrayList<String>();
+ boolean hasInternetTile = false;
+ for (int i = 0; i < tileSplit.length; i++) {
+ String tile = tileSplit[i].trim();
+ if (tile.isEmpty()) continue;
+ tiles.add(tile);
+ if (tile.equals("internet")) hasInternetTile = true;
+ }
+ if (!hasInternetTile) {
+ if (tiles.contains("wifi")) {
+ // Replace the WiFi with Internet, and remove the Cell
+ tiles.set(tiles.indexOf("wifi"), "internet");
+ tiles.remove("cell");
+ } else if (tiles.contains("cell")) {
+ // Replace the Cell with Internet
+ tiles.set(tiles.indexOf("cell"), "internet");
+ }
+ } else {
+ tiles.remove("wifi");
+ tiles.remove("cell");
+ }
+ secureSettings.insertSettingOverrideableByRestoreLocked(
+ Secure.QS_TILES,
+ TextUtils.join(",", tiles),
+ null /* tag */,
+ true /* makeDefault */,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ currentVersion = 205;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml b/packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml
new file mode 100644
index 0000000..181ba07
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2021, 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.
+-->
+<com.android.systemui.qs.QSFooterActionsView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/qs_footer_actions_container"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:gravity="center_vertical">
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@android:id/edit"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:contentDescription="@string/accessibility_quick_settings_edit"
+ android:focusable="true"
+ android:padding="@dimen/qs_footer_icon_padding"
+ android:src="@*android:drawable/ic_mode_edit"
+ android:tint="?android:attr/textColorPrimary" />
+
+ <com.android.systemui.statusbar.phone.MultiUserSwitch
+ android:id="@+id/multi_user_switch"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:focusable="true">
+
+ <ImageView
+ android:id="@+id/multi_user_avatar"
+ android:layout_width="@dimen/multi_user_avatar_expanded_size"
+ android:layout_height="@dimen/multi_user_avatar_expanded_size"
+ android:layout_gravity="center"
+ android:scaleType="centerInside" />
+ </com.android.systemui.statusbar.phone.MultiUserSwitch>
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/pm_lite"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:focusable="true"
+ android:padding="@dimen/qs_footer_icon_padding"
+ android:src="@*android:drawable/ic_lock_power_off"
+ android:contentDescription="@string/accessibility_quick_settings_power_menu"
+ android:tint="?android:attr/textColorPrimary" />
+
+ <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+ android:id="@+id/settings_button_container"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:layout_weight="1"
+ android:clipChildren="false"
+ android:clipToPadding="false">
+
+ <com.android.systemui.statusbar.phone.SettingsButton
+ android:id="@+id/settings_button"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_gravity="center"
+ android:contentDescription="@string/accessibility_quick_settings_settings"
+ android:background="@drawable/qs_footer_action_chip_background_borderless"
+ android:padding="@dimen/qs_footer_icon_padding"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_settings"
+ android:tint="?android:attr/textColorPrimary" />
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/tuner_icon"
+ android:layout_width="8dp"
+ android:layout_height="8dp"
+ android:layout_gravity="center_horizontal|bottom"
+ android:layout_marginBottom="@dimen/qs_footer_icon_padding"
+ android:src="@drawable/tuner"
+ android:tint="?android:attr/textColorTertiary"
+ android:visibility="invisible" />
+
+ </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+
+</com.android.systemui.qs.QSFooterActionsView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/fp_to_unlock.xml b/packages/SystemUI/res/anim/fp_to_unlock.xml
index a348208..a5f75b6 100644
--- a/packages/SystemUI/res/anim/fp_to_unlock.xml
+++ b/packages/SystemUI/res/anim/fp_to_unlock.xml
@@ -19,10 +19,10 @@
<group android:name="_R_G">
<group android:name="_R_G_L_1_G_N_7_T_0" android:translateX="-27" android:translateY="-17.5">
<group android:name="_R_G_L_1_G" android:translateX="30.75" android:translateY="25.75">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " />
- <path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " />
- <path android:name="_R_G_L_1_G_D_2_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " />
- <path android:name="_R_G_L_1_G_D_3_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " />
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " />
+ <path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " />
+ <path android:name="_R_G_L_1_G_D_2_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " />
+ <path android:name="_R_G_L_1_G_D_3_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " />
</group>
</group>
<group android:name="_R_G_L_0_G_N_7_T_0" android:translateX="-27" android:translateY="-17.5">
diff --git a/packages/SystemUI/res/anim/lock_to_unlock.xml b/packages/SystemUI/res/anim/lock_to_unlock.xml
index ec51c01..76f7a05 100644
--- a/packages/SystemUI/res/anim/lock_to_unlock.xml
+++ b/packages/SystemUI/res/anim/lock_to_unlock.xml
@@ -21,7 +21,7 @@
<group android:name="_R_G_L_2_G_N_10_T_1" android:translateX="50.25" android:translateY="61">
<group android:name="_R_G_L_2_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5">
<group android:name="_R_G_L_2_G" android:translateX="-0.375" android:translateY="-22.375">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
</group>
</group>
</group>
@@ -30,7 +30,7 @@
<group android:name="_R_G_L_1_G_N_10_T_1" android:translateX="50.25" android:translateY="61">
<group android:name="_R_G_L_1_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5">
<group android:name="_R_G_L_1_G" android:translateX="5" android:translateY="-22.5">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M2.5 15 C2.5,15 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15,15 15,15 " />
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M2.5 15 C2.5,15 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15,15 15,15 " />
</group>
</group>
</group>
diff --git a/packages/SystemUI/res/drawable/ic_unlock.xml b/packages/SystemUI/res/drawable/ic_unlock.xml
index c3b3469..46023e6 100644
--- a/packages/SystemUI/res/drawable/ic_unlock.xml
+++ b/packages/SystemUI/res/drawable/ic_unlock.xml
@@ -21,7 +21,7 @@
android:strokeColor="#FF000000"
android:strokeLineCap="round"
android:strokeLineJoin="round"
- android:strokeWidth="2.5"
+ android:strokeWidth="2"
android:pathData="M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
</group>
<group android:translateX="14" android:translateY="13.5">
@@ -29,7 +29,7 @@
android:strokeColor="#FF000000"
android:strokeLineCap="round"
android:strokeLineJoin="round"
- android:strokeWidth="2.5"
+ android:strokeWidth="2"
android:pathData="M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " />
</group>
<group android:translateX="20" android:translateY="35.75">
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 317dbc0..fe0b14a 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -68,93 +68,8 @@
</LinearLayout>
- <LinearLayout
- android:id="@+id/qs_footer_actions_container"
- android:layout_width="match_parent"
- android:layout_height="48dp"
- android:gravity="center_vertical">
+ <include layout="@layout/qs_footer_actions"/>
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@android:id/edit"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
- android:layout_weight="1"
- android:background="@drawable/qs_footer_action_chip_background"
- android:clickable="true"
- android:clipToPadding="false"
- android:contentDescription="@string/accessibility_quick_settings_edit"
- android:focusable="true"
- android:padding="@dimen/qs_footer_icon_padding"
- android:src="@*android:drawable/ic_mode_edit"
- android:tint="?android:attr/textColorPrimary" />
-
- <com.android.systemui.statusbar.phone.MultiUserSwitch
- android:id="@+id/multi_user_switch"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
- android:layout_weight="1"
- android:background="@drawable/qs_footer_action_chip_background"
- android:focusable="true">
-
- <ImageView
- android:id="@+id/multi_user_avatar"
- android:layout_width="@dimen/multi_user_avatar_expanded_size"
- android:layout_height="@dimen/multi_user_avatar_expanded_size"
- android:layout_gravity="center"
- android:scaleType="centerInside" />
- </com.android.systemui.statusbar.phone.MultiUserSwitch>
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/pm_lite"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
- android:layout_weight="1"
- android:background="@drawable/qs_footer_action_chip_background"
- android:clickable="true"
- android:clipToPadding="false"
- android:focusable="true"
- android:padding="@dimen/qs_footer_icon_padding"
- android:src="@*android:drawable/ic_lock_power_off"
- android:contentDescription="@string/accessibility_quick_settings_power_menu"
- android:tint="?android:attr/textColorPrimary" />
-
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@+id/settings_button_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:background="@drawable/qs_footer_action_chip_background"
- android:layout_weight="1"
- android:clipChildren="false"
- android:clipToPadding="false">
-
- <com.android.systemui.statusbar.phone.SettingsButton
- android:id="@+id/settings_button"
- android:layout_width="match_parent"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_gravity="center"
- android:contentDescription="@string/accessibility_quick_settings_settings"
- android:background="@drawable/qs_footer_action_chip_background_borderless"
- android:padding="@dimen/qs_footer_icon_padding"
- android:scaleType="centerInside"
- android:src="@drawable/ic_settings"
- android:tint="?android:attr/textColorPrimary" />
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/tuner_icon"
- android:layout_width="8dp"
- android:layout_height="8dp"
- android:layout_gravity="center_horizontal|bottom"
- android:layout_marginBottom="@dimen/qs_footer_icon_padding"
- android:src="@drawable/tuner"
- android:tint="?android:attr/textColorTertiary"
- android:visibility="invisible" />
-
- </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-
- </LinearLayout>
</LinearLayout>
</com.android.systemui.qs.QSFooterView>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index e37a3f0..0c3c602 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -68,7 +68,7 @@
android:id="@+id/lock_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="48px"
+ android:padding="@dimen/lock_icon_padding"
android:layout_gravity="center"
android:scaleType="centerCrop"/>
</com.android.keyguard.LockIconView>
diff --git a/packages/SystemUI/res/layout/udfps_keyguard_view.xml b/packages/SystemUI/res/layout/udfps_keyguard_view.xml
index 18517906..a9eb27a 100644
--- a/packages/SystemUI/res/layout/udfps_keyguard_view.xml
+++ b/packages/SystemUI/res/layout/udfps_keyguard_view.xml
@@ -34,7 +34,7 @@
android:id="@+id/udfps_aod_fp"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="48px"
+ android:padding="@dimen/lock_icon_padding"
android:layout_gravity="center"
android:scaleType="centerCrop"
app:lottie_autoPlay="false"
@@ -46,7 +46,7 @@
android:id="@+id/udfps_lockscreen_fp"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="48px"
+ android:padding="@dimen/lock_icon_padding"
android:layout_gravity="center"
android:scaleType="centerCrop"
app:lottie_autoPlay="false"
diff --git a/packages/SystemUI/res/raw/udfps_aod_fp.json b/packages/SystemUI/res/raw/udfps_aod_fp.json
index 3247fe7..3b273ff 100644
--- a/packages/SystemUI/res/raw/udfps_aod_fp.json
+++ b/packages/SystemUI/res/raw/udfps_aod_fp.json
@@ -164,7 +164,7 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
@@ -526,7 +526,7 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
@@ -829,7 +829,7 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
@@ -1132,7 +1132,7 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
@@ -1507,7 +1507,7 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
@@ -1882,7 +1882,7 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
@@ -2257,7 +2257,7 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
@@ -2560,7 +2560,7 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
diff --git a/packages/SystemUI/res/raw/udfps_lockscreen_fp.json b/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
index a25a475..a30a03a 100644
--- a/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
+++ b/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
@@ -1 +1 @@
-{"v":"5.7.8","fr":60,"ip":0,"op":46,"w":46,"h":65,"nm":"fingerprint_build_on","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Fingerprint_20210701 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23.091,32.5,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999994755,0.949000000954,0.624000012875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[{"tm":210,"cm":"2","dr":0},{"tm":255,"cm":"1","dr":0}]}
\ No newline at end of file
+{"v":"5.7.8","fr":60,"ip":0,"op":46,"w":46,"h":65,"nm":"fingerprint_build_on","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Fingerprint_20210701 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23.091,32.5,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999994755,0.949000000954,0.624000012875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[{"tm":210,"cm":"2","dr":0},{"tm":255,"cm":"1","dr":0}]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 721e1f3..10b0f79 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -110,7 +110,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- internet,wifi,cell,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness
+ internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness
</string>
<!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a12fd2b..28233f8 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -538,6 +538,9 @@
<!-- Gravity for the notification panel -->
<integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
+ <!-- Padding for the lock icon on the keyguard. In pixels - should not scale with display size. -->
+ <dimen name="lock_icon_padding">48px</dimen>
+
<!-- Height of the carrier/wifi name label -->
<dimen name="carrier_label_height">24dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a8812bf..b9002c3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -438,6 +438,8 @@
<string name="fingerprint_dialog_use_fingerprint">Use your fingerprint to continue</string>
<!-- Message shown to ask the user to use screenlock to continue.[CHAR LIMIT=NONE] -->
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock">Can\u2019t recognize fingerprint. Use screen lock instead.</string>
+ <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
+ <string name="keyguard_face_failed_use_fp">@string/fingerprint_dialog_use_fingerprint_instead</string>
<!-- Message shown when the system-provided face dialog is shown, asking for authentication [CHAR LIMIT=30] -->
<string name="face_dialog_looking_for_face">Looking for you\u2026</string>
@@ -3012,6 +3014,8 @@
<string name="pref_title_network_details" msgid="7329759534269363308">"Network details"</string>
<!-- Provider Model: Panel subtitle for tapping a network to connect to internet. [CHAR LIMIT=60] -->
<string name="tap_a_network_to_connect">Tap a network to connect</string>
+ <!-- Provider Model: Panel subtitle for unlocking screen to view networks. [CHAR LIMIT=60] -->
+ <string name="unlock_to_view_networks">Unlock to view networks</string>
<!-- Provider Model: Wi-Fi settings. text displayed when Wi-Fi is on and network list is empty [CHAR LIMIT=50]-->
<string name="wifi_empty_list_wifi_on">Searching for networks\u2026</string>
<!-- Provider Model: Failure notification for connect -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ad196ef..6908409 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -347,13 +347,16 @@
private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms
private static final int HAL_ERROR_RETRY_MAX = 20;
- private final Runnable mCancelNotReceived = new Runnable() {
- @Override
- public void run() {
- Log.w(TAG, "Cancel not received, transitioning to STOPPED");
- mFingerprintRunningState = mFaceRunningState = BIOMETRIC_STATE_STOPPED;
- updateBiometricListeningState();
- }
+ private final Runnable mFpCancelNotReceived = () -> {
+ Log.e(TAG, "Fp cancellation not received, transitioning to STOPPED");
+ mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
+ updateFingerprintListeningState();
+ };
+
+ private final Runnable mFaceCancelNotReceived = () -> {
+ Log.e(TAG, "Face cancellation not received, transitioning to STOPPED");
+ mFaceRunningState = BIOMETRIC_STATE_STOPPED;
+ updateFaceListeningState();
};
private final Handler mHandler;
@@ -791,19 +794,19 @@
private void handleFingerprintError(int msgId, String errString) {
Assert.isMainThread();
- if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mHandler.hasCallbacks(
- mCancelNotReceived)) {
- mHandler.removeCallbacks(mCancelNotReceived);
+ if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
+ mHandler.removeCallbacks(mFpCancelNotReceived);
}
+ // Error is always the end of authentication lifecycle.
+ mFingerprintCancelSignal = null;
+
if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED
&& mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
updateFingerprintListeningState();
} else {
setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
- mFingerprintCancelSignal = null;
- mFaceCancelSignal = null;
}
if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
@@ -905,6 +908,7 @@
private void handleFaceAuthFailed() {
Assert.isMainThread();
+ mFaceCancelSignal = null;
setFaceRunningState(BIOMETRIC_STATE_STOPPED);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -983,10 +987,13 @@
private void handleFaceError(int msgId, String errString) {
Assert.isMainThread();
if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString);
- if (msgId == FaceManager.FACE_ERROR_CANCELED && mHandler.hasCallbacks(mCancelNotReceived)) {
- mHandler.removeCallbacks(mCancelNotReceived);
+ if (mHandler.hasCallbacks(mFaceCancelNotReceived)) {
+ mHandler.removeCallbacks(mFaceCancelNotReceived);
}
+ // Error is always the end of authentication lifecycle
+ mFaceCancelSignal = null;
+
if (msgId == FaceManager.FACE_ERROR_CANCELED
&& mFaceRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
setFaceRunningState(BIOMETRIC_STATE_STOPPED);
@@ -2368,6 +2375,14 @@
}
private void startListeningForFingerprint() {
+ final int userId = getCurrentUser();
+ final boolean unlockPossible = isUnlockWithFingerprintPossible(userId);
+ if (mFingerprintCancelSignal != null) {
+ Log.e(TAG, "Cancellation signal is not null, high chance of bug in fp auth lifecycle"
+ + " management. FP state: " + mFingerprintRunningState
+ + ", unlockPossible: " + unlockPossible);
+ }
+
if (mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING) {
setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
return;
@@ -2377,11 +2392,8 @@
return;
}
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
- int userId = getCurrentUser();
- if (isUnlockWithFingerprintPossible(userId)) {
- if (mFingerprintCancelSignal != null) {
- mFingerprintCancelSignal.cancel();
- }
+
+ if (unlockPossible) {
mFingerprintCancelSignal = new CancellationSignal();
if (isEncryptedOrLockdown(userId)) {
@@ -2397,6 +2409,14 @@
}
private void startListeningForFace() {
+ final int userId = getCurrentUser();
+ final boolean unlockPossible = isUnlockWithFacePossible(userId);
+ if (mFaceCancelSignal != null) {
+ Log.e(TAG, "Cancellation signal is not null, high chance of bug in face auth lifecycle"
+ + " management. Face state: " + mFaceRunningState
+ + ", unlockPossible: " + unlockPossible);
+ }
+
if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING) {
setFaceRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
return;
@@ -2405,11 +2425,8 @@
return;
}
if (DEBUG) Log.v(TAG, "startListeningForFace(): " + mFaceRunningState);
- int userId = getCurrentUser();
- if (isUnlockWithFacePossible(userId)) {
- if (mFaceCancelSignal != null) {
- mFaceCancelSignal.cancel();
- }
+
+ if (unlockPossible) {
mFaceCancelSignal = new CancellationSignal();
// This would need to be updated for multi-sensor devices
@@ -2461,9 +2478,8 @@
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
mFingerprintCancelSignal = null;
- if (!mHandler.hasCallbacks(mCancelNotReceived)) {
- mHandler.postDelayed(mCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
- }
+ mHandler.removeCallbacks(mFpCancelNotReceived);
+ mHandler.postDelayed(mFpCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
}
setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING);
}
@@ -2478,9 +2494,8 @@
if (mFaceCancelSignal != null) {
mFaceCancelSignal.cancel();
mFaceCancelSignal = null;
- if (!mHandler.hasCallbacks(mCancelNotReceived)) {
- mHandler.postDelayed(mCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
- }
+ mHandler.removeCallbacks(mFaceCancelNotReceived);
+ mHandler.postDelayed(mFaceCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
}
setFaceRunningState(BIOMETRIC_STATE_CANCELLING);
}
@@ -2842,6 +2857,11 @@
mSecureCameraLaunched = false;
}
+ if (mKeyguardBypassController != null) {
+ // LS visibility has changed, so reset deviceEntryIntent
+ mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
+ }
+
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index d122610..d46426a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -23,7 +23,6 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
@@ -68,8 +67,6 @@
private float mBurnInProgress;
private float mInterpolatedDarkAmount;
- private ValueAnimator mHintAnimator;
-
public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mFingerprintDrawable = new UdfpsFpDrawable(context);
@@ -94,9 +91,6 @@
new KeyPath("**"), LottieProperty.COLOR_FILTER,
frameInfo -> new PorterDuffColorFilter(mTextColorPrimary, PorterDuff.Mode.SRC_ATOP)
);
-
- mHintAnimator = ObjectAnimator.ofFloat(mLockScreenFp, "progress", 1f, 0f, 1f);
- mHintAnimator.setDuration(4000);
}
@Override
@@ -183,19 +177,11 @@
}
void onDozeAmountChanged(float linear, float eased) {
- mHintAnimator.cancel();
mInterpolatedDarkAmount = eased;
updateAlpha();
updateBurnInOffsets();
}
- void animateHint() {
- if (!isShadeLocked() && !mUdfpsRequested && mAlpha == 255
- && mLockScreenFp.isVisibleToUser()) {
- mHintAnimator.start();
- }
- }
-
/**
* Animates in the bg protection circle behind the fp icon to highlight the icon.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 102dc41..79a4a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -20,14 +20,10 @@
import android.annotation.NonNull;
import android.content.res.Configuration;
-import android.hardware.biometrics.BiometricSourceType;
import android.util.MathUtils;
import android.view.MotionEvent;
-import androidx.annotation.Nullable;
-
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -47,14 +43,8 @@
/**
* Class that coordinates non-HBM animations during keyguard authentication.
- *
- * Highlights the udfps icon when:
- * - Face authentication has failed
- * - Face authentication has been run for > 2 seconds
*/
public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> {
- private static final long AFTER_FACE_AUTH_HINT_DELAY = 2000;
-
@NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@NonNull private final DelayableExecutor mExecutor;
@@ -63,12 +53,10 @@
@NonNull private final ConfigurationController mConfigurationController;
@NonNull private final UdfpsController mUdfpsController;
- @Nullable private Runnable mCancelDelayedHintRunnable;
private boolean mShowingUdfpsBouncer;
private boolean mUdfpsRequested;
private boolean mQsExpanded;
private boolean mFaceDetectRunning;
- private boolean mHintShown;
private int mStatusBarState;
private float mTransitionToFullShadeProgress;
private float mLastDozeAmount;
@@ -111,10 +99,6 @@
@Override
protected void onViewAttached() {
super.onViewAttached();
- mHintShown = false;
- mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
- updateFaceDetectRunning(mKeyguardUpdateMonitor.isFaceDetectionRunning());
-
final float dozeAmount = mStatusBarStateController.getDozeAmount();
mLastDozeAmount = dozeAmount;
mStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
@@ -137,7 +121,6 @@
@Override
protected void onViewDetached() {
super.onViewDetached();
- mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
mFaceDetectRunning = false;
mStatusBarStateController.removeCallback(mStateListener);
@@ -147,11 +130,6 @@
if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) {
mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
}
-
- if (mCancelDelayedHintRunnable != null) {
- mCancelDelayedHintRunnable.run();
- mCancelDelayedHintRunnable = null;
- }
}
@Override
@@ -250,36 +228,6 @@
}
}
- private void cancelDelayedHint() {
- if (mCancelDelayedHintRunnable != null) {
- mCancelDelayedHintRunnable.run();
- mCancelDelayedHintRunnable = null;
- }
- }
-
- private void updateFaceDetectRunning(boolean running) {
- if (mFaceDetectRunning == running) {
- return;
- }
-
- // show udfps hint a few seconds after face auth started running
- if (!mFaceDetectRunning && running && !mHintShown && mCancelDelayedHintRunnable == null) {
- // Face detect started running, show udfps hint after a delay
- mCancelDelayedHintRunnable = mExecutor.executeDelayed(() -> showHint(false),
- AFTER_FACE_AUTH_HINT_DELAY);
- }
-
- mFaceDetectRunning = running;
- }
-
- private void showHint(boolean forceShow) {
- cancelDelayedHint();
- if (!mHintShown || forceShow) {
- mHintShown = true;
- mView.animateHint();
- }
- }
-
/**
* Set the progress we're currently transitioning to the full shade. 0.0f means we're not
* transitioning yet, while 1.0f means we've fully dragged down.
@@ -319,39 +267,6 @@
}
};
- private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
- new KeyguardUpdateMonitorCallback() {
- public void onBiometricRunningStateChanged(boolean running,
- BiometricSourceType biometricSourceType) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- updateFaceDetectRunning(running);
- }
- }
-
- public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- // show udfps hint when face auth fails
- showHint(true);
- }
- }
-
- public void onBiometricError(int msgId, String errString,
- BiometricSourceType biometricSourceType) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- // show udfps hint when face auth fails
- showHint(true);
- }
- }
-
- public void onBiometricAuthenticated(int userId,
- BiometricSourceType biometricSourceType, boolean isStrongBiometric) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- // cancel delayed hint if face auth succeeded
- cancelDelayedHint();
- }
- }
- };
-
private final StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor =
new StatusBarKeyguardViewManager.AlternateAuthInterceptor() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 543004e..1ca2217 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -116,7 +116,7 @@
private final TaskbarDelegate mTaskbarDelegate;
private final NotificationShadeDepthController mNotificationShadeDepthController;
private int mNavMode;
- private boolean mIsTablet;
+ @VisibleForTesting boolean mIsTablet;
private final UserTracker mUserTracker;
/** A displayId - nav bar maps. */
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 2bf4bf4..aaa3bf0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -106,7 +106,7 @@
static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
- SystemProperties.getBoolean("persist.debug.per_window_input_rotation", true);
+ SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
private ISystemGestureExclusionListener mGestureExclusionListener =
new ISystemGestureExclusionListener.Stub() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index ce1066e..1bd3664 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -268,7 +268,7 @@
}
@Override
- public void setExpansion(float expansion) {
+ public void setExpansion(float expansion, float proposedTranslation) {
mLastExpansion = expansion;
updateSelected();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index e38bd4b..0e0681b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -35,11 +35,6 @@
void setExpanded(boolean expanded);
/**
- * Returns the full height of the footer.
- */
- int getHeight();
-
- /**
* Sets the percentage amount that the quick settings has been expanded.
*
* @param expansion A value from 1 to 0 that indicates how much the quick settings have been
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt
new file mode 100644
index 0000000..dbf62a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt
@@ -0,0 +1,167 @@
+package com.android.systemui.qs
+
+import android.content.Intent
+import android.os.UserManager
+import android.provider.Settings
+import android.view.View
+import android.widget.Toast
+import androidx.annotation.VisibleForTesting
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.nano.MetricsProto
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R
+import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED
+import com.android.systemui.statusbar.phone.MultiUserSwitchController
+import com.android.systemui.statusbar.phone.SettingsButton
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener
+import com.android.systemui.tuner.TunerService
+import com.android.systemui.util.ViewController
+import javax.inject.Inject
+import javax.inject.Named
+
+class QSFooterActionsController @Inject constructor(
+ view: QSFooterActionsView,
+ private val qsPanelController: QSPanelController,
+ private val activityStarter: ActivityStarter,
+ private val userManager: UserManager,
+ private val userInfoController: UserInfoController,
+ private val multiUserSwitchController: MultiUserSwitchController,
+ private val deviceProvisionedController: DeviceProvisionedController,
+ private val falsingManager: FalsingManager,
+ private val metricsLogger: MetricsLogger,
+ private val tunerService: TunerService,
+ private val globalActionsDialog: GlobalActionsDialogLite,
+ private val uiEventLogger: UiEventLogger,
+ @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean
+) : ViewController<QSFooterActionsView>(view) {
+
+ private var listening: Boolean = false
+ var expanded = false
+ set(value) {
+ field = value
+ mView.setExpanded(value, isTunerEnabled(),
+ multiUserSwitchController.isMultiUserEnabled)
+ }
+
+ private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button)
+ private val settingsButtonContainer: View? = view.findViewById(R.id.settings_button_container)
+ private val editButton: View = view.findViewById(android.R.id.edit)
+ private val powerMenuLite: View = view.findViewById(R.id.pm_lite)
+
+ private val onUserInfoChangedListener = OnUserInfoChangedListener { _, picture, _ ->
+ val isGuestUser: Boolean = userManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser())
+ mView.onUserInfoChanged(picture, isGuestUser)
+ }
+
+ private val onClickListener = View.OnClickListener { v ->
+ // Don't do anything until views are unhidden. Don't do anything if the tap looks
+ // suspicious.
+ if (!expanded || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return@OnClickListener
+ }
+ if (v === settingsButton) {
+ if (!deviceProvisionedController.isCurrentUserSetup) {
+ // If user isn't setup just unlock the device and dump them back at SUW.
+ activityStarter.postQSRunnableDismissingKeyguard {}
+ return@OnClickListener
+ }
+ metricsLogger.action(
+ if (expanded) MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+ else MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH)
+ if (settingsButton.isTunerClick) {
+ activityStarter.postQSRunnableDismissingKeyguard {
+ if (isTunerEnabled()) {
+ tunerService.showResetRequest {
+ // Relaunch settings so that the tuner disappears.
+ startSettingsActivity()
+ }
+ } else {
+ Toast.makeText(context, R.string.tuner_toast, Toast.LENGTH_LONG).show()
+ tunerService.isTunerEnabled = true
+ }
+ startSettingsActivity()
+ }
+ } else {
+ startSettingsActivity()
+ }
+ } else if (v === powerMenuLite) {
+ uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
+ globalActionsDialog.showOrHideDialog(false, true)
+ }
+ }
+
+ override fun onInit() {
+ multiUserSwitchController.init()
+ }
+
+ private fun startSettingsActivity() {
+ val animationController = settingsButtonContainer?.let {
+ ActivityLaunchAnimator.Controller.fromView(
+ it,
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON)
+ }
+ activityStarter.startActivity(Intent(Settings.ACTION_SETTINGS),
+ true /* dismissShade */, animationController)
+ }
+
+ @VisibleForTesting
+ public override fun onViewAttached() {
+ if (showPMLiteButton) {
+ powerMenuLite.visibility = View.VISIBLE
+ powerMenuLite.setOnClickListener(onClickListener)
+ } else {
+ powerMenuLite.visibility = View.GONE
+ }
+ settingsButton.setOnClickListener(onClickListener)
+ editButton.setOnClickListener(View.OnClickListener { view: View? ->
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return@OnClickListener
+ }
+ activityStarter.postQSRunnableDismissingKeyguard { qsPanelController.showEdit(view) }
+ })
+
+ mView.updateEverything(isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled)
+ }
+
+ override fun onViewDetached() {
+ setListening(false)
+ }
+
+ fun setListening(listening: Boolean) {
+ if (this.listening == listening) {
+ return
+ }
+ this.listening = listening
+ if (this.listening) {
+ userInfoController.addCallback(onUserInfoChangedListener)
+ } else {
+ userInfoController.removeCallback(onUserInfoChangedListener)
+ }
+ }
+
+ fun disable(state2: Int) {
+ mView.disable(state2, isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled)
+ }
+
+ fun setExpansion(headerExpansionFraction: Float) {
+ mView.setExpansion(headerExpansionFraction)
+ }
+
+ fun updateAnimator(width: Int, numTiles: Int) {
+ mView.updateAnimator(width, numTiles)
+ }
+
+ fun setKeyguardShowing() {
+ mView.setKeyguardShowing()
+ }
+
+ private fun isTunerEnabled() = tunerService.isTunerEnabled
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt
new file mode 100644
index 0000000..66a29a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2021 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.systemui.qs
+
+import android.app.StatusBarManager
+import android.content.Context
+import android.content.res.Configuration
+import android.graphics.PorterDuff
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.RippleDrawable
+import android.os.UserManager
+import android.util.AttributeSet
+import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import com.android.settingslib.Utils
+import com.android.settingslib.drawable.UserIconDrawable
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.MultiUserSwitch
+import com.android.systemui.statusbar.phone.SettingsButton
+
+/**
+ * Quick Settings bottom buttons placed in footer (aka utility bar) - always visible in expanded QS,
+ * in split shade mode visible also in collapsed state. May contain up to 5 buttons: settings,
+ * edit tiles, power off and conditionally: user switch and tuner
+ */
+class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
+ private lateinit var settingsContainer: View
+ private lateinit var settingsButton: SettingsButton
+ private lateinit var multiUserSwitch: MultiUserSwitch
+ private lateinit var multiUserAvatar: ImageView
+ private lateinit var tunerIcon: View
+ private lateinit var editTilesButton: View
+
+ private var settingsCogAnimator: TouchAnimator? = null
+
+ private var qsDisabled = false
+ private var isExpanded = false
+ private var expansionAmount = 0f
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ editTilesButton = requireViewById(android.R.id.edit)
+ settingsButton = findViewById(R.id.settings_button)
+ settingsContainer = findViewById(R.id.settings_button_container)
+ multiUserSwitch = findViewById(R.id.multi_user_switch)
+ multiUserAvatar = multiUserSwitch.findViewById(R.id.multi_user_avatar)
+ tunerIcon = requireViewById(R.id.tuner_icon)
+
+ // RenderThread is doing more harm than good when touching the header (to expand quick
+ // settings), so disable it for this view
+ if (settingsButton.background is RippleDrawable) {
+ (settingsButton.background as RippleDrawable).setForceSoftware(true)
+ }
+ updateResources()
+ importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
+ }
+
+ fun updateAnimator(width: Int, numTiles: Int) {
+ val size = (mContext.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size) -
+ mContext.resources.getDimensionPixelSize(R.dimen.qs_tile_padding))
+ val remaining = (width - numTiles * size) / (numTiles - 1)
+ val defSpace = mContext.resources.getDimensionPixelOffset(R.dimen.default_gear_space)
+ val translation = if (isLayoutRtl) (remaining - defSpace) else -(remaining - defSpace)
+ settingsCogAnimator = TouchAnimator.Builder()
+ .addFloat(settingsButton, "translationX", translation.toFloat(), 0f)
+ .addFloat(settingsButton, "rotation", -120f, 0f)
+ .build()
+ setExpansion(expansionAmount)
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+ updateResources()
+ }
+
+ override fun onRtlPropertiesChanged(layoutDirection: Int) {
+ super.onRtlPropertiesChanged(layoutDirection)
+ updateResources()
+ }
+
+ private fun updateResources() {
+ val tunerIconTranslation = mContext.resources
+ .getDimensionPixelOffset(R.dimen.qs_footer_tuner_icon_translation).toFloat()
+ tunerIcon.translationX = if (isLayoutRtl) (-tunerIconTranslation) else tunerIconTranslation
+ }
+
+ fun setKeyguardShowing() {
+ setExpansion(expansionAmount)
+ }
+
+ fun setExpanded(expanded: Boolean, isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
+ if (isExpanded == expanded) return
+ isExpanded = expanded
+ updateEverything(isTunerEnabled, multiUserEnabled)
+ }
+
+ fun setExpansion(headerExpansionFraction: Float) {
+ expansionAmount = headerExpansionFraction
+ if (settingsCogAnimator != null) settingsCogAnimator!!.setPosition(headerExpansionFraction)
+ }
+
+ fun disable(state2: Int, isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
+ val disabled = state2 and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0
+ if (disabled == qsDisabled) return
+ qsDisabled = disabled
+ updateEverything(isTunerEnabled, multiUserEnabled)
+ }
+
+ fun updateEverything(isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
+ post {
+ updateVisibilities(isTunerEnabled, multiUserEnabled)
+ updateClickabilities()
+ isClickable = false
+ }
+ }
+
+ private fun updateClickabilities() {
+ multiUserSwitch.isClickable = multiUserSwitch.visibility == VISIBLE
+ editTilesButton.isClickable = editTilesButton.visibility == VISIBLE
+ settingsButton.isClickable = settingsButton.visibility == VISIBLE
+ }
+
+ private fun updateVisibilities(isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
+ settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE
+ tunerIcon.visibility = if (isTunerEnabled) VISIBLE else INVISIBLE
+ multiUserSwitch.visibility = if (showUserSwitcher(multiUserEnabled)) VISIBLE else GONE
+ val isDemo = UserManager.isDeviceInDemoMode(context)
+ settingsButton.visibility = if (isDemo || !isExpanded) INVISIBLE else VISIBLE
+ }
+
+ private fun showUserSwitcher(multiUserEnabled: Boolean): Boolean {
+ return isExpanded && multiUserEnabled
+ }
+
+ fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) {
+ var pictureToSet = picture
+ if (picture != null && isGuestUser && picture !is UserIconDrawable) {
+ pictureToSet = picture.constantState.newDrawable(resources).mutate()
+ pictureToSet.setColorFilter(
+ Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground),
+ PorterDuff.Mode.SRC_IN)
+ }
+ multiUserAvatar.setImageDrawable(pictureToSet)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
index 57438d1..7db13bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
@@ -21,60 +21,40 @@
import android.content.Context;
import android.content.res.Configuration;
import android.database.ContentObserver;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import com.android.settingslib.Utils;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
-import com.android.settingslib.drawable.UserIconDrawable;
import com.android.systemui.R;
-import com.android.systemui.qs.TouchAnimator.Builder;
-import com.android.systemui.statusbar.phone.MultiUserSwitch;
-import com.android.systemui.statusbar.phone.SettingsButton;
-/** */
+/**
+ * Footer of expanded Quick Settings, tiles page indicator, (optionally) build number and
+ * {@link QSFooterActionsView}
+ */
public class QSFooterView extends FrameLayout {
- private SettingsButton mSettingsButton;
- protected View mSettingsContainer;
private PageIndicator mPageIndicator;
private TextView mBuildText;
- private boolean mShouldShowBuildText;
-
- private boolean mQsDisabled;
-
- private boolean mExpanded;
-
- private boolean mListening;
-
- protected MultiUserSwitch mMultiUserSwitch;
- private ImageView mMultiUserAvatar;
+ private View mActionsContainer;
protected TouchAnimator mFooterAnimator;
+
+ private boolean mQsDisabled;
+ private boolean mExpanded;
private float mExpansionAmount;
- protected View mEdit;
- private TouchAnimator mSettingsCogAnimator;
-
- private View mActionsContainer;
- private View mTunerIcon;
- private int mTunerIconTranslation;
+ private boolean mShouldShowBuildText;
private OnClickListener mExpandClickListener;
@@ -94,27 +74,11 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mEdit = requireViewById(android.R.id.edit);
-
mPageIndicator = findViewById(R.id.footer_page_indicator);
-
- mSettingsButton = findViewById(R.id.settings_button);
- mSettingsContainer = findViewById(R.id.settings_button_container);
-
- mMultiUserSwitch = findViewById(R.id.multi_user_switch);
- mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
-
mActionsContainer = requireViewById(R.id.qs_footer_actions_container);
mBuildText = findViewById(R.id.build);
- mTunerIcon = requireViewById(R.id.tuner_icon);
- // RenderThread is doing more harm than good when touching the header (to expand quick
- // settings), so disable it for this view
- if (mSettingsButton.getBackground() instanceof RippleDrawable) {
- ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
- }
updateResources();
-
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
setBuildText();
}
@@ -137,18 +101,7 @@
}
}
- void updateAnimator(int width, int numTiles) {
- int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size)
- - mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_padding);
- int remaining = (width - numTiles * size) / (numTiles - 1);
- int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space);
-
- mSettingsCogAnimator = new Builder()
- .addFloat(mSettingsButton, "translationX",
- isLayoutRtl() ? (remaining - defSpace) : -(remaining - defSpace), 0)
- .addFloat(mSettingsButton, "rotation", -120, 0)
- .build();
-
+ void updateExpansion() {
setExpansion(mExpansionAmount);
}
@@ -158,20 +111,11 @@
updateResources();
}
- @Override
- public void onRtlPropertiesChanged(int layoutDirection) {
- super.onRtlPropertiesChanged(layoutDirection);
- updateResources();
- }
-
private void updateResources() {
updateFooterAnimator();
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
lp.bottomMargin = getResources().getDimensionPixelSize(R.dimen.qs_footers_margin_bottom);
setLayoutParams(lp);
- mTunerIconTranslation = mContext.getResources()
- .getDimensionPixelOffset(R.dimen.qs_footer_tuner_icon_translation);
- mTunerIcon.setTranslationX(isLayoutRtl() ? -mTunerIconTranslation : mTunerIconTranslation);
}
private void updateFooterAnimator() {
@@ -197,17 +141,15 @@
mExpandClickListener = onClickListener;
}
- void setExpanded(boolean expanded, boolean isTunerEnabled, boolean multiUserEnabled) {
+ void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
- updateEverything(isTunerEnabled, multiUserEnabled);
+ updateEverything();
}
/** */
public void setExpansion(float headerExpansionFraction) {
mExpansionAmount = headerExpansionFraction;
- if (mSettingsCogAnimator != null) mSettingsCogAnimator.setPosition(headerExpansionFraction);
-
if (mFooterAnimator != null) {
mFooterAnimator.setPosition(headerExpansionFraction);
}
@@ -228,14 +170,6 @@
super.onDetachedFromWindow();
}
- /** */
- public void setListening(boolean listening) {
- if (listening == mListening) {
- return;
- }
- mListening = listening;
- }
-
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (action == AccessibilityNodeInfo.ACTION_EXPAND) {
@@ -253,50 +187,26 @@
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
}
- void disable(int state2, boolean isTunerEnabled, boolean multiUserEnabled) {
+ void disable(int state2) {
final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
- updateEverything(isTunerEnabled, multiUserEnabled);
+ updateEverything();
}
- void updateEverything(boolean isTunerEnabled, boolean multiUserEnabled) {
+ void updateEverything() {
post(() -> {
- updateVisibilities(isTunerEnabled, multiUserEnabled);
+ updateVisibilities();
updateClickabilities();
setClickable(false);
});
}
private void updateClickabilities() {
- mMultiUserSwitch.setClickable(mMultiUserSwitch.getVisibility() == View.VISIBLE);
- mEdit.setClickable(mEdit.getVisibility() == View.VISIBLE);
- mSettingsButton.setClickable(mSettingsButton.getVisibility() == View.VISIBLE);
mBuildText.setLongClickable(mBuildText.getVisibility() == View.VISIBLE);
}
- private void updateVisibilities(boolean isTunerEnabled, boolean multiUserEnabled) {
- mSettingsContainer.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
- mTunerIcon.setVisibility(isTunerEnabled ? View.VISIBLE : View.INVISIBLE);
- final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
- mMultiUserSwitch.setVisibility(
- showUserSwitcher(multiUserEnabled) ? View.VISIBLE : View.GONE);
- mSettingsButton.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
-
+ private void updateVisibilities() {
mBuildText.setVisibility(mExpanded && mShouldShowBuildText ? View.VISIBLE : View.INVISIBLE);
}
-
- private boolean showUserSwitcher(boolean multiUserEnabled) {
- return mExpanded && multiUserEnabled;
- }
-
- void onUserInfoChanged(Drawable picture, boolean isGuestUser) {
- if (picture != null && isGuestUser && !(picture instanceof UserIconDrawable)) {
- picture = picture.getConstantState().newDrawable(getResources()).mutate();
- picture.setColorFilter(
- Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground),
- Mode.SRC_IN);
- }
- mMultiUserAvatar.setImageDrawable(picture);
- }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
index 929aeda..c8ae590 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -16,39 +16,19 @@
package com.android.systemui.qs;
-import static com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED;
-
import android.content.ClipData;
import android.content.ClipboardManager;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.os.UserManager;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
-import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.globalactions.GlobalActionsDialogLite;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.MultiUserSwitchController;
-import com.android.systemui.statusbar.phone.SettingsButton;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
-import javax.inject.Named;
/**
* Controller for {@link QSFooterView}.
@@ -56,137 +36,45 @@
@QSScope
public class QSFooterViewController extends ViewController<QSFooterView> implements QSFooter {
- private final UserManager mUserManager;
- private final UserInfoController mUserInfoController;
- private final ActivityStarter mActivityStarter;
- private final DeviceProvisionedController mDeviceProvisionedController;
private final UserTracker mUserTracker;
private final QSPanelController mQsPanelController;
private final QuickQSPanelController mQuickQSPanelController;
- private final TunerService mTunerService;
- private final MetricsLogger mMetricsLogger;
- private final FalsingManager mFalsingManager;
- private final MultiUserSwitchController mMultiUserSwitchController;
- private final SettingsButton mSettingsButton;
- private final View mSettingsButtonContainer;
+ private final QSFooterActionsController mQsFooterActionsController;
private final TextView mBuildText;
- private final View mEdit;
private final PageIndicator mPageIndicator;
- private final View mPowerMenuLite;
- private final boolean mShowPMLiteButton;
- private final GlobalActionsDialogLite mGlobalActionsDialog;
- private final UiEventLogger mUiEventLogger;
-
- private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
- new UserInfoController.OnUserInfoChangedListener() {
- @Override
- public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
- boolean isGuestUser = mUserManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser());
- mView.onUserInfoChanged(picture, isGuestUser);
- }
- };
-
- private final View.OnClickListener mSettingsOnClickListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Don't do anything until views are unhidden. Don't do anything if the tap looks
- // suspicious.
- if (!mExpanded || mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
- return;
- }
-
- if (v == mSettingsButton) {
- if (!mDeviceProvisionedController.isCurrentUserSetup()) {
- // If user isn't setup just unlock the device and dump them back at SUW.
- mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
- });
- return;
- }
- mMetricsLogger.action(
- mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
- : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
- if (mSettingsButton.isTunerClick()) {
- mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
- if (isTunerEnabled()) {
- mTunerService.showResetRequest(
- () -> {
- // Relaunch settings so that the tuner disappears.
- startSettingsActivity();
- });
- } else {
- Toast.makeText(getContext(), R.string.tuner_toast,
- Toast.LENGTH_LONG).show();
- mTunerService.setTunerEnabled(true);
- }
- startSettingsActivity();
-
- });
- } else {
- startSettingsActivity();
- }
- } else if (v == mPowerMenuLite) {
- mUiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS);
- mGlobalActionsDialog.showOrHideDialog(false, true);
- }
- }
- };
-
- private boolean mListening;
- private boolean mExpanded;
@Inject
- QSFooterViewController(QSFooterView view, UserManager userManager,
- UserInfoController userInfoController, ActivityStarter activityStarter,
- DeviceProvisionedController deviceProvisionedController, UserTracker userTracker,
+ QSFooterViewController(QSFooterView view,
+ UserTracker userTracker,
QSPanelController qsPanelController,
- MultiUserSwitchController multiUserSwitchController,
QuickQSPanelController quickQSPanelController,
- TunerService tunerService, MetricsLogger metricsLogger, FalsingManager falsingManager,
- @Named(PM_LITE_ENABLED) boolean showPMLiteButton,
- GlobalActionsDialogLite globalActionsDialog, UiEventLogger uiEventLogger) {
+ QSFooterActionsController qsFooterActionsController) {
super(view);
- mUserManager = userManager;
- mUserInfoController = userInfoController;
- mActivityStarter = activityStarter;
- mDeviceProvisionedController = deviceProvisionedController;
mUserTracker = userTracker;
mQsPanelController = qsPanelController;
mQuickQSPanelController = quickQSPanelController;
- mTunerService = tunerService;
- mMetricsLogger = metricsLogger;
- mFalsingManager = falsingManager;
- mMultiUserSwitchController = multiUserSwitchController;
+ mQsFooterActionsController = qsFooterActionsController;
- mSettingsButton = mView.findViewById(R.id.settings_button);
- mSettingsButtonContainer = mView.findViewById(R.id.settings_button_container);
mBuildText = mView.findViewById(R.id.build);
- mEdit = mView.findViewById(android.R.id.edit);
mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
- mPowerMenuLite = mView.findViewById(R.id.pm_lite);
- mShowPMLiteButton = showPMLiteButton;
- mGlobalActionsDialog = globalActionsDialog;
- mUiEventLogger = uiEventLogger;
}
@Override
protected void onInit() {
super.onInit();
- mMultiUserSwitchController.init();
+ mQsFooterActionsController.init();
}
@Override
protected void onViewAttached() {
- if (mShowPMLiteButton) {
- mPowerMenuLite.setVisibility(View.VISIBLE);
- mPowerMenuLite.setOnClickListener(mSettingsOnClickListener);
- } else {
- mPowerMenuLite.setVisibility(View.GONE);
- }
mView.addOnLayoutChangeListener(
- (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
- mView.updateAnimator(
- right - left, mQuickQSPanelController.getNumQuickTiles()));
- mSettingsButton.setOnClickListener(mSettingsOnClickListener);
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ mView.updateExpansion();
+ mQsFooterActionsController.updateAnimator(right - left,
+ mQuickQSPanelController.getNumQuickTiles());
+ }
+ );
+
mBuildText.setOnLongClickListener(view -> {
CharSequence buildText = mBuildText.getText();
if (!TextUtils.isEmpty(buildText)) {
@@ -200,17 +88,8 @@
}
return false;
});
-
- mEdit.setOnClickListener(view -> {
- if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
- return;
- }
- mActivityStarter.postQSRunnableDismissingKeyguard(() ->
- mQsPanelController.showEdit(view));
- });
-
mQsPanelController.setFooterPageIndicator(mPageIndicator);
- mView.updateEverything(isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
+ mView.updateEverything();
}
@Override
@@ -225,38 +104,25 @@
@Override
public void setExpanded(boolean expanded) {
- mExpanded = expanded;
- mView.setExpanded(
- expanded, isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
- }
-
- @Override
- public int getHeight() {
- return mView.getHeight();
+ mQsFooterActionsController.setExpanded(expanded);
+ mView.setExpanded(expanded);
}
@Override
public void setExpansion(float expansion) {
mView.setExpansion(expansion);
+ mQsFooterActionsController.setExpansion(expansion);
}
@Override
public void setListening(boolean listening) {
- if (mListening == listening) {
- return;
- }
-
- mListening = listening;
- if (mListening) {
- mUserInfoController.addCallback(mOnUserInfoChangedListener);
- } else {
- mUserInfoController.removeCallback(mOnUserInfoChangedListener);
- }
+ mQsFooterActionsController.setListening(listening);
}
@Override
public void setKeyguardShowing(boolean keyguardShowing) {
mView.setKeyguardShowing();
+ mQsFooterActionsController.setKeyguardShowing();
}
/** */
@@ -267,19 +133,7 @@
@Override
public void disable(int state1, int state2, boolean animate) {
- mView.disable(state2, isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
- }
-
- private void startSettingsActivity() {
- ActivityLaunchAnimator.Controller animationController =
- mSettingsButtonContainer != null ? ActivityLaunchAnimator.Controller.fromView(
- mSettingsButtonContainer,
- InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON) : null;
- mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
- true /* dismissShade */, animationController);
- }
-
- private boolean isTunerEnabled() {
- return mTunerService.isTunerEnabled();
+ mView.disable(state2);
+ mQsFooterActionsController.disable(state2);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 4e09bc6..4242e1b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -510,11 +510,13 @@
: headerTranslation);
}
int currentHeight = getView().getHeight();
- mLastHeaderTranslation = headerTranslation;
- if (expansion == mLastQSExpansion && mLastKeyguardAndExpanded == onKeyguardAndExpanded
- && mLastViewHeight == currentHeight) {
+ if (expansion == mLastQSExpansion
+ && mLastKeyguardAndExpanded == onKeyguardAndExpanded
+ && mLastViewHeight == currentHeight
+ && mLastHeaderTranslation == headerTranslation) {
return;
}
+ mLastHeaderTranslation = headerTranslation;
mLastQSExpansion = expansion;
mLastKeyguardAndExpanded = onKeyguardAndExpanded;
mLastViewHeight = currentHeight;
@@ -534,8 +536,8 @@
}
mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
mQSPanelController.setRevealExpansion(expansion);
- mQSPanelController.getTileLayout().setExpansion(expansion);
- mQuickQSPanelController.getTileLayout().setExpansion(expansion);
+ mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
+ mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
mQSPanelScrollView.setTranslationY(translationScaleY * heightDiff);
if (fullyCollapsed) {
mQSPanelScrollView.setScrollY(0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 63124ab..28aa884 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -736,7 +736,7 @@
void setListening(boolean listening, UiEventLogger uiEventLogger);
/**
- * Set the minimum number of rows to show
+ * Sets the minimum number of rows to show
*
* @param minRows the minimum.
*/
@@ -745,7 +745,7 @@
}
/**
- * Set the max number of columns to show
+ * Sets the max number of columns to show
*
* @param maxColumns the maximum
*
@@ -755,7 +755,10 @@
return false;
}
- default void setExpansion(float expansion) {}
+ /**
+ * Sets the expansion value and proposedTranslation to panel.
+ */
+ default void setExpansion(float expansion, float proposedTranslation) {}
int getNumVisibleTiles();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 240cf93..541ee2c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -39,7 +39,6 @@
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -512,33 +511,6 @@
}
}
}
- // TODO(b/174753536): Move it into the config file.
- // Only do the below hacking when at least one of the below tiles exist
- // --InternetTile
- // --WiFiTile
- // --CellularTIle
- if (tiles.contains("internet") || tiles.contains("wifi") || tiles.contains("cell")) {
- if (FeatureFlags.isProviderModelSettingEnabled(context)) {
- if (!tiles.contains("internet")) {
- if (tiles.contains("wifi")) {
- // Replace the WiFi with Internet, and remove the Cell
- tiles.set(tiles.indexOf("wifi"), "internet");
- tiles.remove("cell");
- } else if (tiles.contains("cell")) {
- // Replace the Cell with Internet
- tiles.set(tiles.indexOf("cell"), "internet");
- }
- } else {
- tiles.remove("wifi");
- tiles.remove("cell");
- }
- } else {
- if (tiles.contains("internet")) {
- tiles.set(tiles.indexOf("internet"), "wifi");
- tiles.add("cell");
- }
- }
- }
return tiles;
}
@@ -558,14 +530,6 @@
&& GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
}
- // TODO(b/174753536): Change the config file directly.
- // Filter out unused tiles from the default QS config.
- if (FeatureFlags.isProviderModelSettingEnabled(context)) {
- tiles.remove("cell");
- tiles.remove("wifi");
- } else {
- tiles.remove("internet");
- }
return tiles;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index f1c1e12..613e7f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -171,6 +171,8 @@
static class QQSSideLabelTileLayout extends SideLabelTileLayout {
+ private boolean mLastSelected;
+
QQSSideLabelTileLayout(Context context) {
super(context, null);
setClipChildren(false);
@@ -216,5 +218,29 @@
}
}
}
+
+ @Override
+ public void setExpansion(float expansion, float proposedTranslation) {
+ if (expansion > 0f && expansion < 1f) {
+ return;
+ }
+ // The cases we must set select for marquee when QQS/QS collapsed, and QS full expanded.
+ // Expansion == 0f is when QQS is fully showing (as opposed to 1f, which is QS). At this
+ // point we want them to be selected so the tiles will marquee (but not at other points
+ // of expansion.
+ boolean selected = (expansion == 1f || proposedTranslation < 0f);
+ if (mLastSelected == selected) {
+ return;
+ }
+ // We set it as not important while we change this, so setting each tile as selected
+ // will not cause them to announce themselves until the user has actually selected the
+ // item.
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ for (int i = 0; i < getChildCount(); i++) {
+ getChildAt(i).setSelected(selected);
+ }
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ mLastSelected = selected;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 1770807..3c2f35b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -34,7 +34,6 @@
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.qs.QSTileHost;
@@ -63,7 +62,6 @@
private final Executor mBgExecutor;
private final Context mContext;
private final UserTracker mUserTracker;
- private final FeatureFlags mFeatureFlags;
private TileStateListener mListener;
private boolean mFinished;
@@ -73,14 +71,12 @@
Context context,
UserTracker userTracker,
@Main Executor mainExecutor,
- @Background Executor bgExecutor,
- FeatureFlags featureFlags
+ @Background Executor bgExecutor
) {
mContext = context;
mMainExecutor = mainExecutor;
mBgExecutor = bgExecutor;
mUserTracker = userTracker;
- mFeatureFlags = featureFlags;
}
public void setListener(TileStateListener listener) {
@@ -121,19 +117,11 @@
}
final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
- // TODO(b/174753536): Move it into the config file.
- if (mFeatureFlags.isProviderModelSettingEnabled()) {
- possibleTiles.remove("cell");
- possibleTiles.remove("wifi");
- } else {
- possibleTiles.remove("internet");
- }
for (String spec : possibleTiles) {
// Only add current and stock tiles that can be created from QSFactoryImpl.
// Do not include CustomTile. Those will be created by `addPackageTiles`.
if (spec.startsWith(CustomTile.PREFIX)) continue;
- // TODO(b/174753536): Move it into the config file.
final QSTile tile = host.createTile(spec);
if (tile == null) {
continue;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 2046550..2de2d04 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -28,6 +28,7 @@
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSContainerImpl;
import com.android.systemui.qs.QSFooter;
+import com.android.systemui.qs.QSFooterActionsView;
import com.android.systemui.qs.QSFooterView;
import com.android.systemui.qs.QSFooterViewController;
import com.android.systemui.qs.QSFragment;
@@ -122,6 +123,12 @@
/** */
@Provides
+ static QSFooterActionsView providesQSFooterActionsView(@RootView View view) {
+ return view.findViewById(R.id.qs_footer_actions_container);
+ }
+
+ /** */
+ @Provides
@QSScope
static QSFooter providesQSFooter(QSFooterViewController qsFooterViewController) {
qsFooterViewController.init();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 70685a6..222539d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -195,9 +195,6 @@
// sibling methods to have special behavior for labelContainer.
labelContainer.forceUnspecifiedMeasure = true
secondaryLabel.alpha = 0f
- // Do not marque in QQS
- label.ellipsize = TextUtils.TruncateAt.END
- secondaryLabel.ellipsize = TextUtils.TruncateAt.END
}
setLabelColor(getLabelColorForState(QSTile.State.DEFAULT_STATE))
setSecondaryLabelColor(getSecondaryLabelColorForState(QSTile.State.DEFAULT_STATE))
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index a63d1f8..e338750 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -287,14 +287,22 @@
}
showProgressBar();
setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular());
- setConnectedWifiLayout();
- boolean isWifiEnabled = mWifiManager.isWifiEnabled();
- mWiFiToggle.setChecked(isWifiEnabled);
- int visible = isWifiEnabled ? View.VISIBLE : View.GONE;
- mWifiRecyclerView.setVisibility(visible);
- mAdapter.notifyDataSetChanged();
- mSeeAllLayout.setVisibility(visible);
- mSpace.setVisibility(isWifiEnabled ? View.GONE : View.VISIBLE);
+
+ final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
+ final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+ updateWifiToggle(isWifiEnabled, isDeviceLocked);
+ updateConnectedWifi(isWifiEnabled, isDeviceLocked);
+
+ List<WifiEntry> wifiEntryList = mInternetDialogController.getWifiEntryList();
+ final int wifiListVisibility =
+ (isDeviceLocked || wifiEntryList == null || wifiEntryList.size() <= 0)
+ ? View.GONE : View.VISIBLE;
+ mWifiRecyclerView.setVisibility(wifiListVisibility);
+ if (wifiListVisibility == View.VISIBLE) {
+ mAdapter.notifyDataSetChanged();
+ }
+ mSeeAllLayout.setVisibility(wifiListVisibility);
+ mSpace.setVisibility(wifiListVisibility == View.VISIBLE ? View.GONE : View.VISIBLE);
}
private void setOnClickListener() {
@@ -358,8 +366,14 @@
}
}
- private void setConnectedWifiLayout() {
- if (!mWifiManager.isWifiEnabled() || mConnectedWifiEntry == null) {
+ private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) {
+ mWiFiToggle.setChecked(isWifiEnabled);
+ mTurnWifiOnLayout.setBackground(
+ (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null);
+ }
+
+ private void updateConnectedWifi(boolean isWifiEnabled, boolean isDeviceLocked) {
+ if (!isWifiEnabled || mConnectedWifiEntry == null || isDeviceLocked) {
mConnectedWifListLayout.setBackground(null);
mConnectedWifListLayout.setVisibility(View.GONE);
return;
@@ -418,7 +432,8 @@
}
protected void showProgressBar() {
- if (mWifiManager == null || !mWifiManager.isWifiEnabled()) {
+ if (mWifiManager == null || !mWifiManager.isWifiEnabled()
+ || mInternetDialogController.isDeviceLocked()) {
setProgressBarVisible(false);
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 890dcfd..80a93d6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -67,6 +67,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.util.settings.GlobalSettings;
@@ -97,6 +98,8 @@
private static final int SUBTITLE_TEXT_WIFI_IS_OFF = R.string.wifi_is_off;
private static final int SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT =
R.string.tap_a_network_to_connect;
+ private static final int SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS =
+ R.string.unlock_to_view_networks;
private static final int SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS =
R.string.wifi_empty_list_wifi_on;
private static final int SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE =
@@ -137,6 +140,9 @@
@VisibleForTesting
protected WifiUtils.InternetIconInjector mWifiIconInjector;
+ @VisibleForTesting
+ KeyguardStateController mKeyguardStateController;
+
private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -161,7 +167,7 @@
@Nullable WifiManager wifiManager, ConnectivityManager connectivityManager,
@Main Handler handler, @Main Executor mainExecutor,
BroadcastDispatcher broadcastDispatcher, KeyguardUpdateMonitor keyguardUpdateMonitor,
- GlobalSettings globalSettings) {
+ GlobalSettings globalSettings, KeyguardStateController keyguardStateController) {
if (DEBUG) {
Log.d(TAG, "Init InternetDialogController");
}
@@ -175,6 +181,7 @@
mSubscriptionManager = subscriptionManager;
mBroadcastDispatcher = broadcastDispatcher;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mKeyguardStateController = keyguardStateController;
mConnectionStateFilter = new IntentFilter();
mConnectionStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mConnectionStateFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
@@ -272,6 +279,15 @@
return mContext.getText(SUBTITLE_TEXT_WIFI_IS_OFF);
}
+ if (isDeviceLocked()) {
+ // When the device is locked.
+ // Sub-Title: Unlock to view networks
+ if (DEBUG) {
+ Log.d(TAG, "The device is locked.");
+ }
+ return mContext.getText(SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS);
+ }
+
final List<ScanResult> wifiList = mWifiManager.getScanResults();
if (wifiList != null && wifiList.size() != 0) {
return mContext.getText(SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT);
@@ -683,6 +699,10 @@
&& serviceState.getState() == serviceState.STATE_IN_SERVICE;
}
+ public boolean isDeviceLocked() {
+ return !mKeyguardStateController.isUnlocked();
+ }
+
boolean activeNetworkIsCellular() {
if (mConnectivityManager == null) {
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index eb72296..ad7c522 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -427,6 +427,19 @@
}
};
+ private final BroadcastReceiver mDebugAnyPackageChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String[] stringArrayExtra = intent.getStringArrayExtra(
+ Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+ Log.e("b/188806432", intent.toString()
+ + (stringArrayExtra != null
+ ? ", EXTRA_CHANGED_COMPONENT_NAME_LIST: " + String.join(", ",
+ stringArrayExtra)
+ : ""));
+ }
+ };
+
private final ServiceConnection mOverviewServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -566,6 +579,13 @@
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
mContext.registerReceiver(mLauncherStateChangedReceiver, filter);
+ // b/188806432
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ filter.addDataSchemeSpecificPart("", PatternMatcher.PATTERN_PREFIX);
+ mContext.registerReceiver(mDebugAnyPackageChangedReceiver, filter);
+
// Listen for status bar state changes
statusBarWinController.registerCallback(mStatusBarWindowCallback);
mScreenshotHelper = new ScreenshotHelper(context);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 3890c1a..503b5c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -825,7 +825,11 @@
if (mKeyguardUpdateMonitor.isUdfpsAvailable()) {
// if udfps available, there will always be a tappable affordance to unlock
// For example, the lock icon
- showTransientIndication(R.string.keyguard_unlock_press);
+ if (mKeyguardBypassController.getUserHasDeviceEntryIntent()) {
+ showTransientIndication(R.string.keyguard_unlock_press);
+ } else {
+ showTransientIndication(R.string.keyguard_face_failed_use_fp);
+ }
} else {
showTransientIndication(R.string.keyguard_try_fingerprint);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index f317628..dbf115b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -2255,6 +2255,11 @@
@Override
public void onClick(View view) {
+ // If the ringer drawer isn't open, don't let anything in it be clicked.
+ if (!mIsRingerDrawerOpen) {
+ return;
+ }
+
setRingerMode(mClickedRingerMode);
mRingerDrawerIconAnimatingSelected = getDrawerIconViewForMode(mClickedRingerMode);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 7e733a9..7e3553a 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -55,6 +55,7 @@
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
+import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
@@ -213,6 +214,13 @@
}
//
+ // Freeform (optional feature)
+ //
+
+ @BindsOptionalOf
+ abstract Optional<FreeformTaskListener> optionalFreeformTaskListener();
+
+ //
// Hide display cutout
//
@@ -328,9 +336,11 @@
@WMSingleton
@Provides
static Transitions provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool,
- Context context, @ShellMainThread ShellExecutor mainExecutor,
+ DisplayController displayController, Context context,
+ @ShellMainThread ShellExecutor mainExecutor,
@ShellAnimationThread ShellExecutor animExecutor) {
- return new Transitions(organizer, pool, context, mainExecutor, animExecutor);
+ return new Transitions(organizer, pool, displayController, context, mainExecutor,
+ animExecutor);
}
//
@@ -451,6 +461,7 @@
Optional<AppPairsController> appPairsOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
+ Optional<Optional<FreeformTaskListener>> freeformTaskListener,
Transitions transitions,
StartingWindowController startingWindow,
@ShellMainThread ShellExecutor mainExecutor) {
@@ -463,6 +474,7 @@
appPairsOptional,
pipTouchHandlerOptional,
fullscreenTaskListener,
+ freeformTaskListener,
transitions,
startingWindow,
mainExecutor);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index be7813e..6397ce6 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -36,6 +36,7 @@
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
+import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
@@ -89,6 +90,18 @@
}
//
+ // Freeform
+ //
+
+ @WMSingleton
+ @Provides
+ static Optional<FreeformTaskListener> provideFreeformTaskListener(
+ Context context,
+ SyncTransactionQueue syncQueue) {
+ return Optional.ofNullable(FreeformTaskListener.create(context, syncQueue));
+ }
+
+ //
// Split/multiwindow
//
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
index 79b0dd0..8e1b13c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
@@ -69,7 +69,7 @@
whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
.thenReturn(true)
whenever(mediaHost.hostView).thenReturn(hostView)
-
+ hostView.layoutParams = FrameLayout.LayoutParams(100, 100)
keyguardMediaController = KeyguardMediaController(
mediaHost,
bypassController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 8fd2a32..3ea57be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -142,6 +142,8 @@
@Test
public void testCreateNavigationBarsIncludeDefaultTrue() {
+ // Tablets may be using taskbar and the logic is different
+ mNavigationBarController.mIsTablet = false;
doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
mNavigationBarController.createNavigationBars(true, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt
new file mode 100644
index 0000000..9378b2b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt
@@ -0,0 +1,91 @@
+package com.android.systemui.qs
+
+import com.android.systemui.R
+import android.os.UserManager
+import android.view.LayoutInflater
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.testing.FakeMetricsLogger
+import com.android.systemui.Dependency
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.phone.MultiUserSwitchController
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.tuner.TunerService
+import com.android.systemui.utils.leaks.FakeTunerService
+import com.android.systemui.utils.leaks.LeakCheckedTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+class QSFooterActionsControllerTest : LeakCheckedTest() {
+ @Mock
+ private lateinit var userManager: UserManager
+ @Mock
+ private lateinit var activityStarter: ActivityStarter
+ @Mock
+ private lateinit var deviceProvisionedController: DeviceProvisionedController
+ @Mock
+ private lateinit var userInfoController: UserInfoController
+ @Mock
+ private lateinit var qsPanelController: QSPanelController
+ @Mock
+ private lateinit var multiUserSwitchController: MultiUserSwitchController
+ @Mock
+ private lateinit var globalActionsDialog: GlobalActionsDialogLite
+ @Mock
+ private lateinit var uiEventLogger: UiEventLogger
+ @Mock
+ private lateinit var controller: QSFooterActionsController
+
+ private val metricsLogger: MetricsLogger = FakeMetricsLogger()
+ private lateinit var view: QSFooterActionsView
+ private val falsingManager: FalsingManagerFake = FalsingManagerFake()
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ injectLeakCheckedDependencies(*LeakCheckedTest.ALL_SUPPORTED_CLASSES)
+ val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService
+
+ view = LayoutInflater.from(context)
+ .inflate(R.layout.qs_footer_actions, null) as QSFooterActionsView
+
+ controller = QSFooterActionsController(view, qsPanelController, activityStarter,
+ userManager, userInfoController, multiUserSwitchController,
+ deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService,
+ globalActionsDialog, uiEventLogger, showPMLiteButton = true)
+ controller.init()
+ controller.onViewAttached()
+ }
+
+ @Test
+ fun testLogPowerMenuClick() {
+ controller.expanded = true
+ falsingManager.setFalseTap(false)
+
+ view.findViewById<View>(R.id.pm_lite).performClick()
+ // Verify clicks are logged
+ verify(uiEventLogger, Mockito.times(1))
+ .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
+ }
+
+ @Test
+ fun testSettings_UserNotSetup() {
+ whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(false)
+ view.findViewById<View>(R.id.settings_button).performClick()
+ // Verify Settings wasn't launched.
+ verify<ActivityStarter>(activityStarter, Mockito.never()).startActivity(any(), anyBoolean())
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
index 6f7bf3b..8c6c358 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
@@ -18,16 +18,11 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ClipData;
import android.content.ClipboardManager;
-import android.os.UserManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
@@ -35,21 +30,8 @@
import androidx.test.filters.SmallTest;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.testing.FakeMetricsLogger;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.globalactions.GlobalActionsDialogLite;
-import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.MultiUserSwitchController;
-import com.android.systemui.statusbar.phone.SettingsButton;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.utils.leaks.FakeTunerService;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import org.junit.Before;
@@ -67,14 +49,6 @@
@Mock
private QSFooterView mView;
@Mock
- private UserManager mUserManager;
- @Mock
- private ActivityStarter mActivityStarter;
- @Mock
- private DeviceProvisionedController mDeviceProvisionedController;
- @Mock
- private UserInfoController mUserInfoController;
- @Mock
private UserTracker mUserTracker;
@Mock
private QSPanelController mQSPanelController;
@@ -82,36 +56,19 @@
private ClipboardManager mClipboardManager;
@Mock
private QuickQSPanelController mQuickQSPanelController;
- private FakeTunerService mFakeTunerService;
- private MetricsLogger mMetricsLogger = new FakeMetricsLogger();
- private FalsingManagerFake mFalsingManager;
-
- @Mock
- private SettingsButton mSettingsButton;
@Mock
private TextView mBuildText;
@Mock
- private View mEdit;
- @Mock
- private MultiUserSwitchController mMultiUserSwitchController;
- @Mock
- private View mPowerMenuLiteView;
- @Mock
- private GlobalActionsDialogLite mGlobalActionsDialog;
- @Mock
- private UiEventLogger mUiEventLogger;
+ private QSFooterActionsController mQSFooterActionsController;
private QSFooterViewController mController;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
- mFalsingManager = new FalsingManagerFake();
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
- mFakeTunerService = (FakeTunerService) Dependency.get(TunerService.class);
-
mContext.addMockSystemService(ClipboardManager.class, mClipboardManager);
when(mView.getContext()).thenReturn(mContext);
@@ -119,16 +76,10 @@
when(mUserTracker.getUserContext()).thenReturn(mContext);
when(mView.isAttachedToWindow()).thenReturn(true);
- when(mView.findViewById(R.id.settings_button)).thenReturn(mSettingsButton);
when(mView.findViewById(R.id.build)).thenReturn(mBuildText);
- when(mView.findViewById(android.R.id.edit)).thenReturn(mEdit);
- when(mView.findViewById(R.id.pm_lite)).thenReturn(mPowerMenuLiteView);
- mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
- mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
- mMultiUserSwitchController, mQuickQSPanelController, mFakeTunerService,
- mMetricsLogger, mFalsingManager, false, mGlobalActionsDialog,
- mUiEventLogger);
+ mController = new QSFooterViewController(mView, mUserTracker, mQSPanelController,
+ mQuickQSPanelController, mQSFooterActionsController);
mController.init();
}
@@ -148,40 +99,4 @@
verify(mClipboardManager).setPrimaryClip(captor.capture());
assertThat(captor.getValue().getItemAt(0).getText()).isEqualTo(text);
}
-
- @Test
- public void testSettings_UserNotSetup() {
- ArgumentCaptor<View.OnClickListener> onClickCaptor =
- ArgumentCaptor.forClass(View.OnClickListener.class);
- verify(mSettingsButton).setOnClickListener(onClickCaptor.capture());
-
- when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(false);
-
- onClickCaptor.getValue().onClick(mSettingsButton);
- // Verify Settings wasn't launched.
- verify(mActivityStarter, never()).startActivity(any(), anyBoolean());
- }
-
- @Test
- public void testLogPowerMenuClick() {
- // Enable power menu button
- mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
- mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
- mMultiUserSwitchController, mQuickQSPanelController, mFakeTunerService,
- mMetricsLogger, new FalsingManagerFake(), true, mGlobalActionsDialog,
- mUiEventLogger);
- mController.init();
- mController.setExpanded(true);
- mFalsingManager.setFalseTap(false);
-
- ArgumentCaptor<View.OnClickListener> onClickCaptor =
- ArgumentCaptor.forClass(View.OnClickListener.class);
- verify(mPowerMenuLiteView).setOnClickListener(onClickCaptor.capture());
-
- onClickCaptor.getValue().onClick(mPowerMenuLiteView);
-
- // Verify clicks are logged
- verify(mUiEventLogger, times(1))
- .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 3b78632..9e97f80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -44,7 +44,6 @@
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.CollectionUtils;
@@ -53,7 +52,6 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -71,15 +69,12 @@
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.settings.SecureSettings;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -133,16 +128,9 @@
private Handler mHandler;
private TestableLooper mLooper;
private QSTileHost mQSTileHost;
- MockitoSession mMockingSession = null;
@Before
public void setUp() {
- // TODO(b/174753536): Remove the mMockingSession when
- // FeatureFlagUtils.SETTINGS_PROVIDER_MODEL is removed.
- mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
- .mockStatic(FeatureFlags.class).startMocking();
- ExtendedMockito.doReturn(false)
- .when(() -> FeatureFlags.isProviderModelSettingEnabled(mContext));
MockitoAnnotations.initMocks(this);
mLooper = TestableLooper.get(this);
mHandler = new Handler(mLooper.getLooper());
@@ -156,13 +144,6 @@
.thenReturn("");
}
- @After
- public void tearDown() throws Exception {
- if (mMockingSession != null) {
- mMockingSession.finishMocking();
- }
- }
-
private void setUpTileFactory() {
when(mMockState.toString()).thenReturn(MOCK_STATE_STRING);
// Only create this kind of tiles
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index a6d044a..4efcc5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -45,17 +45,14 @@
import android.testing.TestableLooper;
import android.text.TextUtils;
import android.util.ArraySet;
-import android.util.FeatureFlagUtils;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.logging.InstanceId;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
@@ -64,7 +61,6 @@
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -74,8 +70,6 @@
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
import java.util.ArrayList;
import java.util.Arrays;
@@ -114,7 +108,6 @@
private PackageManager mPackageManager;
@Mock
private UserTracker mUserTracker;
- @Mock private FeatureFlags mFeatureFlags;
@Captor
private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
@@ -122,18 +115,10 @@
private TileQueryHelper mTileQueryHelper;
private FakeExecutor mMainExecutor;
private FakeExecutor mBgExecutor;
- MockitoSession mMockingSession = null;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- // TODO(b/174753536): Remove the mMockingSession when
- // FeatureFlagUtils.SETTINGS_PROVIDER_MODEL is removed.
- mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
- .mockStatic(FeatureFlagUtils.class).startMocking();
- ExtendedMockito.doReturn(false).when(() -> FeatureFlagUtils.isEnabled(mContext,
- FeatureFlagUtils.SETTINGS_PROVIDER_MODEL));
-
mContext.setMockPackageManager(mPackageManager);
mState = new QSTile.State();
@@ -153,17 +138,10 @@
mMainExecutor = new FakeExecutor(clock);
mBgExecutor = new FakeExecutor(clock);
mTileQueryHelper = new TileQueryHelper(
- mContext, mUserTracker, mMainExecutor, mBgExecutor, mFeatureFlags);
+ mContext, mUserTracker, mMainExecutor, mBgExecutor);
mTileQueryHelper.setListener(mListener);
}
- @After
- public void tearDown() throws Exception {
- if (mMockingSession != null) {
- mMockingSession.finishMocking();
- }
- }
-
@Test
public void testIsFinished_falseBeforeQuerying() {
assertFalse(mTileQueryHelper.isFinished());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index f876a43..2b3624e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -33,13 +33,13 @@
import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.settingslib.Utils;
import com.android.settingslib.wifi.WifiUtils;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -79,7 +79,7 @@
@Mock
private GlobalSettings mGlobalSettings;
@Mock
- private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private KeyguardStateController mKeyguardStateController;
@Mock
private NetworkController.AccessPointController mAccessPointController;
@Mock
@@ -99,15 +99,16 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+ doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
when(mWifiManager.getConnectionInfo()).thenReturn(mWifiInfo);
+ when(mKeyguardStateController.isUnlocked()).thenReturn(true);
when(mConnectedEntry.isDefaultNetwork()).thenReturn(true);
mInternetDialogController = new MockInternetDialogController(mContext,
mock(UiEventLogger.class), mock(ActivityStarter.class), mAccessPointController,
mSubscriptionManager, mTelephonyManager, mWifiManager,
mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
- mKeyguardUpdateMonitor, mGlobalSettings);
+ mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController);
mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
mInternetDialogController.mOnSubscriptionsChangedListener);
mInternetDialogController.onStart(
@@ -174,6 +175,16 @@
}
@Test
+ public void getSubtitleText_deviceLockedWithWifiOn_returnUnlockToViewNetworks() {
+ mInternetDialogController.setAirplaneModeEnabled(false);
+ when(mWifiManager.isWifiEnabled()).thenReturn(true);
+ when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+ assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false),
+ getResourcesString("unlock_to_view_networks")));
+ }
+
+ @Test
public void getSubtitleText_withNoService_returnNoNetworksAvailable() {
mInternetDialogController.setAirplaneModeEnabled(false);
when(mWifiManager.isWifiEnabled()).thenReturn(true);
@@ -311,6 +322,20 @@
verify(mActivityStarter).postStartActivityDismissingKeyguard(any(Intent.class), anyInt());
}
+ @Test
+ public void isDeviceLocked_keyguardIsUnlocked_returnFalse() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+
+ assertThat(mInternetDialogController.isDeviceLocked()).isFalse();
+ }
+
+ @Test
+ public void isDeviceLocked_keyguardIsLocked_returnTrue() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+ assertThat(mInternetDialogController.isDeviceLocked()).isTrue();
+ }
+
private String getResourcesString(String name) {
return mContext.getResources().getString(getResourcesId(name));
}
@@ -331,10 +356,12 @@
@Nullable WifiManager wifiManager, ConnectivityManager connectivityManager,
@Main Handler handler, @Main Executor mainExecutor,
BroadcastDispatcher broadcastDispatcher,
- KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings) {
+ KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings,
+ KeyguardStateController keyguardStateController) {
super(context, uiEventLogger, starter, accessPointController, subscriptionManager,
telephonyManager, wifiManager, connectivityManager, handler, mainExecutor,
- broadcastDispatcher, keyguardUpdateMonitor, globalSettings);
+ broadcastDispatcher, keyguardUpdateMonitor, globalSettings,
+ keyguardStateController);
mGlobalSettings = globalSettings;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index 856e3a1..de2c7e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -59,24 +59,31 @@
private static final String WIFI_TITLE = "Connected Wi-Fi Title";
private static final String WIFI_SUMMARY = "Connected Wi-Fi Summary";
- private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
-
- private InternetDialogFactory mInternetDialogFactory = mock(InternetDialogFactory.class);
- private InternetAdapter mInternetAdapter = mock(InternetAdapter.class);
- private InternetDialogController mInternetDialogController = mock(
- InternetDialogController.class);
- private InternetDialogController.InternetDialogCallback mCallback =
- mock(InternetDialogController.InternetDialogCallback.class);
- private MockInternetDialog mInternetDialog;
- private WifiReceiver mWifiReceiver = null;
- private WifiManager mMockWifiManager = mock(WifiManager.class);
- private TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
@Mock
- private WifiEntry mWifiEntry = mock(WifiEntry.class);
+ private InternetDialogFactory mInternetDialogFactory;
@Mock
- private WifiInfo mWifiInfo;
+ private InternetDialogController mInternetDialogController;
+ @Mock
+ private UiEventLogger mUiEventLogger;
@Mock
private Handler mHandler;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private InternetAdapter mInternetAdapter;
+ @Mock
+ private WifiManager mMockWifiManager;
+ @Mock
+ private WifiEntry mWifiEntry;
+ @Mock
+ private WifiInfo mWifiInfo;
+
+ private MockInternetDialog mInternetDialog;
+ private WifiReceiver mWifiReceiver;
+ private LinearLayout mWifiToggle;
+ private LinearLayout mConnectedWifi;
+ private RecyclerView mWifiList;
+ private LinearLayout mSeeAll;
@Before
public void setUp() {
@@ -99,6 +106,10 @@
when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
when(mInternetDialogController.getWifiEntryList()).thenReturn(Arrays.asList(mWifiEntry));
+ mWifiToggle = mInternetDialog.mDialogView.requireViewById(R.id.turn_on_wifi_layout);
+ mConnectedWifi = mInternetDialog.mDialogView.requireViewById(R.id.wifi_connected_layout);
+ mWifiList = mInternetDialog.mDialogView.requireViewById(R.id.wifi_list_layout);
+ mSeeAll = mInternetDialog.mDialogView.requireViewById(R.id.see_all_layout);
}
@After
@@ -137,7 +148,7 @@
}
@Test
- public void updateDialog_withWifiOnAndHasConnectedWifi_connectedWifiLayoutVisible() {
+ public void updateDialog_wifiOnAndHasConnectedWifi_showConnectedWifi() {
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
@@ -147,36 +158,85 @@
mInternetDialog.updateDialog();
- final LinearLayout linearLayout = mInternetDialog.mDialogView.requireViewById(
- R.id.wifi_connected_layout);
- assertThat(linearLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
- public void updateDialog_withWifiOnAndNoConnectedWifi_connectedWifiLayoutGone() {
+ public void updateDialog_wifiOnAndNoConnectedWifi_hideConnectedWifi() {
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
- mInternetDialog.updateDialog();
- final LinearLayout linearLayout = mInternetDialog.mDialogView.requireViewById(
- R.id.wifi_connected_layout);
- assertThat(linearLayout.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialog.updateDialog();
+
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
}
@Test
- public void updateDialog_withWifiOff_WifiRecycleViewGone() {
- when(mMockWifiManager.isWifiEnabled()).thenReturn(false);
- mInternetDialog.updateDialog();
- final RecyclerView view = mInternetDialog.mDialogView.requireViewById(
- R.id.wifi_list_layout);
+ public void updateDialog_wifiOnAndNoWifiList_hideWifiListAndSeeAll() {
+ when(mInternetDialogController.getWifiEntryList()).thenReturn(null);
- assertThat(view.getVisibility()).isEqualTo(View.GONE);
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
}
@Test
- public void onClickSeeMoreButton_clickSeeMore_verifyLaunchNetworkSetting() {
- final LinearLayout seeAllLayout = mInternetDialog.mDialogView.requireViewById(
- R.id.see_all_layout);
- seeAllLayout.performClick();
+ public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
+ List<WifiEntry> wifiEntries = new ArrayList<WifiEntry>();
+ wifiEntries.add(mWifiEntry);
+ when(mInternetDialogController.getWifiEntryList()).thenReturn(wifiEntries);
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void updateDialog_deviceLockedAndHasConnectedWifi_showHighlightWifiToggle() {
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+ when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
+ when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+ when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
+ when(mWifiEntry.isDefaultNetwork()).thenReturn(true);
+ mInternetDialog.mConnectedWifiEntry = mWifiEntry;
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiToggle.getBackground()).isNotNull();
+ }
+
+ @Test
+ public void updateDialog_deviceLockedAndHasConnectedWifi_hideConnectedWifi() {
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+ when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
+ when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+ when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
+ when(mWifiEntry.isDefaultNetwork()).thenReturn(true);
+ mInternetDialog.mConnectedWifiEntry = mWifiEntry;
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_deviceLockedAndHasWifiList_hideWifiListAndSeeAll() {
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+ List<WifiEntry> wifiEntries = new ArrayList<WifiEntry>();
+ wifiEntries.add(mWifiEntry);
+ when(mInternetDialogController.getWifiEntryList()).thenReturn(wifiEntries);
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() {
+ mSeeAll.performClick();
verify(mInternetDialogController).launchNetworkSetting();
}
@@ -193,6 +253,17 @@
}
@Test
+ public void showProgressBar_deviceLocked_hideProgressBar() {
+ Mockito.reset(mHandler);
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+ mInternetDialog.showProgressBar();
+
+ assertThat(mInternetDialog.mIsProgressBarVisible).isFalse();
+ verify(mHandler, never()).postDelayed(any(Runnable.class), anyLong());
+ }
+
+ @Test
public void showProgressBar_wifiEnabledWithWifiEntry_showProgressBarThenHide() {
Mockito.reset(mHandler);
when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index cd332a6..4946ad4 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -125,7 +125,7 @@
// connect with remote AppPredictionService instead for dark launch
usesPeopleService = false;
}
- final boolean serviceExists = resolveService(sessionId, false,
+ final boolean serviceExists = resolveService(sessionId, true,
usesPeopleService, s -> s.onCreatePredictionSession(context, sessionId));
if (serviceExists && !mSessionInfos.containsKey(sessionId)) {
final AppPredictionSessionInfo sessionInfo = new AppPredictionSessionInfo(
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index a56b1db..5aec6aa 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -3285,57 +3285,6 @@
}
}
- private void applyResourceOverlaysToWidgetsLocked(Set<String> packageNames, int userId,
- boolean updateFrameworkRes) {
- for (int i = 0, N = mProviders.size(); i < N; i++) {
- Provider provider = mProviders.get(i);
- if (provider.getUserId() != userId) {
- continue;
- }
-
- final String packageName = provider.id.componentName.getPackageName();
- if (!updateFrameworkRes && !packageNames.contains(packageName)) {
- continue;
- }
-
- ApplicationInfo newAppInfo = null;
- try {
- newAppInfo = mPackageManager.getApplicationInfo(packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES, userId);
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to retrieve app info for " + packageName
- + " userId=" + userId, e);
- }
- if (newAppInfo == null) {
- continue;
- }
- ApplicationInfo oldAppInfo = provider.info.providerInfo.applicationInfo;
- if (!newAppInfo.sourceDir.equals(oldAppInfo.sourceDir)) {
- // Overlay paths are generated against a particular version of an application.
- // The overlays paths of a newly upgraded application are incompatible with the
- // old version of the application.
- continue;
- }
-
- // Isolate the changes relating to RROs. The app info must be copied to prevent
- // affecting other parts of system server that may have cached this app info.
- oldAppInfo = new ApplicationInfo(oldAppInfo);
- oldAppInfo.overlayPaths = newAppInfo.overlayPaths.clone();
- oldAppInfo.resourceDirs = newAppInfo.resourceDirs.clone();
- provider.info.providerInfo.applicationInfo = oldAppInfo;
-
- for (int j = 0, M = provider.widgets.size(); j < M; j++) {
- Widget widget = provider.widgets.get(j);
- if (widget.views != null) {
- widget.views.updateAppInfo(oldAppInfo);
- }
- if (widget.maskedViews != null) {
- widget.maskedViews.updateAppInfo(oldAppInfo);
- }
- }
- }
- }
-
/**
* Updates all providers with the specified package names, and records any providers that were
* pruned.
@@ -4926,14 +4875,5 @@
public void unlockUser(int userId) {
handleUserUnlocked(userId);
}
-
- @Override
- public void applyResourceOverlaysToWidgets(Set<String> packageNames, int userId,
- boolean updateFrameworkRes) {
- synchronized (mLock) {
- applyResourceOverlaysToWidgetsLocked(new HashSet<>(packageNames), userId,
- updateFrameworkRes);
- }
- }
}
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 282b868..689890f 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -92,6 +92,7 @@
name: "services.core.unboosted",
defaults: ["platform_service_defaults"],
srcs: [
+ ":android.hardware.biometrics.face-V1-java-source",
":statslog-art-java-gen",
":services.core-sources",
":services.core.protologsrc",
@@ -116,6 +117,7 @@
libs: [
"services.net",
+ "android.hardware.common-V2-java",
"android.hardware.light-V2.0-java",
"android.hardware.gnss-V1-java",
"android.hardware.power-V1-java",
@@ -145,7 +147,6 @@
"android.hardware.light-V1-java",
"android.hardware.tv.cec-V1.1-java",
"android.hardware.weaver-V1.0-java",
- "android.hardware.biometrics.face-V1-java",
"android.hardware.biometrics.face-V1.0-java",
"android.hardware.biometrics.fingerprint-V2.3-java",
"android.hardware.biometrics.fingerprint-V1-java",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 0621d0f..e390ae28 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -353,6 +353,12 @@
/**
+ * Retrieve all receivers that can handle a broadcast of the given intent.
+ */
+ public abstract List<ResolveInfo> queryIntentReceivers(Intent intent,
+ String resolvedType, int flags, int filterCallingUid, int userId);
+
+ /**
* Retrieve all services that can be performed for the given intent.
* @see PackageManager#queryIntentServices(Intent, int)
*/
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 047aae7..aae1cc0 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -147,6 +147,47 @@
return true;
}
+ /**
+ * Returns whether an intent matches the IntentFilter with a pre-resolved type.
+ */
+ public static boolean intentMatchesFilter(
+ IntentFilter filter, Intent intent, String resolvedType) {
+ final boolean debug = localLOGV
+ || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
+
+ final Printer logPrinter = debug
+ ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM) : null;
+
+ if (debug) {
+ Slog.v(TAG, "Intent: " + intent);
+ Slog.v(TAG, "Matching against filter: " + filter);
+ filter.dump(logPrinter, " ");
+ }
+
+ final int match = filter.match(intent.getAction(), resolvedType, intent.getScheme(),
+ intent.getData(), intent.getCategories(), TAG);
+
+ if (match >= 0) {
+ if (debug) {
+ Slog.v(TAG, "Filter matched! match=0x" + Integer.toHexString(match));
+ }
+ return true;
+ } else {
+ if (debug) {
+ final String reason;
+ switch (match) {
+ case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
+ case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
+ case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
+ case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
+ default: reason = "unknown reason"; break;
+ }
+ Slog.v(TAG, "Filter did not match: " + reason);
+ }
+ return false;
+ }
+ }
+
private ArrayList<F> collectFilters(F[] array, IntentFilter matching) {
ArrayList<F> res = null;
if (array != null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 35ed477..0d8cbaf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -193,7 +193,6 @@
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetManagerInternal;
import android.content.AttributionSource;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
@@ -12628,76 +12627,72 @@
int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
List<ResolveInfo> receivers = null;
- try {
- HashSet<ComponentName> singleUserReceivers = null;
- boolean scannedFirstReceivers = false;
- for (int user : users) {
- // Skip users that have Shell restrictions
- if (callingUid == SHELL_UID
- && mUserController.hasUserRestriction(
- UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
- continue;
- }
- List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
- .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
- if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
- // If this is not the system user, we need to check for
- // any receivers that should be filtered out.
- for (int i=0; i<newReceivers.size(); i++) {
- ResolveInfo ri = newReceivers.get(i);
- if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
- newReceivers.remove(i);
- i--;
- }
+ HashSet<ComponentName> singleUserReceivers = null;
+ boolean scannedFirstReceivers = false;
+ for (int user : users) {
+ // Skip users that have Shell restrictions
+ if (callingUid == SHELL_UID
+ && mUserController.hasUserRestriction(
+ UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
+ continue;
+ }
+ List<ResolveInfo> newReceivers = mPackageManagerInt
+ .queryIntentReceivers(intent, resolvedType, pmFlags, callingUid, user);
+ if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
+ // If this is not the system user, we need to check for
+ // any receivers that should be filtered out.
+ for (int i = 0; i < newReceivers.size(); i++) {
+ ResolveInfo ri = newReceivers.get(i);
+ if ((ri.activityInfo.flags & ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
+ newReceivers.remove(i);
+ i--;
}
}
- if (newReceivers != null && newReceivers.size() == 0) {
- newReceivers = null;
- }
- if (receivers == null) {
- receivers = newReceivers;
- } else if (newReceivers != null) {
- // We need to concatenate the additional receivers
- // found with what we have do far. This would be easy,
- // but we also need to de-dup any receivers that are
- // singleUser.
- if (!scannedFirstReceivers) {
- // Collect any single user receivers we had already retrieved.
- scannedFirstReceivers = true;
- for (int i=0; i<receivers.size(); i++) {
- ResolveInfo ri = receivers.get(i);
- if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
- ComponentName cn = new ComponentName(
- ri.activityInfo.packageName, ri.activityInfo.name);
- if (singleUserReceivers == null) {
- singleUserReceivers = new HashSet<ComponentName>();
- }
- singleUserReceivers.add(cn);
- }
- }
- }
- // Add the new results to the existing results, tracking
- // and de-dupping single user receivers.
- for (int i=0; i<newReceivers.size(); i++) {
- ResolveInfo ri = newReceivers.get(i);
+ }
+ if (newReceivers != null && newReceivers.size() == 0) {
+ newReceivers = null;
+ }
+ if (receivers == null) {
+ receivers = newReceivers;
+ } else if (newReceivers != null) {
+ // We need to concatenate the additional receivers
+ // found with what we have do far. This would be easy,
+ // but we also need to de-dup any receivers that are
+ // singleUser.
+ if (!scannedFirstReceivers) {
+ // Collect any single user receivers we had already retrieved.
+ scannedFirstReceivers = true;
+ for (int i = 0; i < receivers.size(); i++) {
+ ResolveInfo ri = receivers.get(i);
if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
ComponentName cn = new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name);
if (singleUserReceivers == null) {
singleUserReceivers = new HashSet<ComponentName>();
}
- if (!singleUserReceivers.contains(cn)) {
- singleUserReceivers.add(cn);
- receivers.add(ri);
- }
- } else {
- receivers.add(ri);
+ singleUserReceivers.add(cn);
}
}
}
+ // Add the new results to the existing results, tracking
+ // and de-dupping single user receivers.
+ for (int i = 0; i < newReceivers.size(); i++) {
+ ResolveInfo ri = newReceivers.get(i);
+ if ((ri.activityInfo.flags & ActivityInfo.FLAG_SINGLE_USER) != 0) {
+ ComponentName cn = new ComponentName(
+ ri.activityInfo.packageName, ri.activityInfo.name);
+ if (singleUserReceivers == null) {
+ singleUserReceivers = new HashSet<ComponentName>();
+ }
+ if (!singleUserReceivers.contains(cn)) {
+ singleUserReceivers.add(cn);
+ receivers.add(ri);
+ }
+ } else {
+ receivers.add(ri);
+ }
+ }
}
- } catch (RemoteException ex) {
- // pm is in same process, this will never happen.
}
if (receivers != null && broadcastAllowList != null) {
for (int i = receivers.size() - 1; i >= 0; i--) {
@@ -13331,8 +13326,7 @@
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// Need to resolve the intent to interested receivers...
- if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
- == 0) {
+ if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
receivers = collectReceiverComponents(
intent, resolvedType, callingUid, users, broadcastAllowList);
}
@@ -16658,13 +16652,6 @@
if (updateFrameworkRes) {
ParsingPackageUtils.readConfigUseRoundIcon(null);
}
-
- AppWidgetManagerInternal widgets = LocalServices.getService(AppWidgetManagerInternal.class);
- if (widgets != null) {
- widgets.applyResourceOverlaysToWidgets(new HashSet<>(packagesToUpdate), userId,
- updateFrameworkRes);
- }
-
mProcessList.updateApplicationInfoLOSP(packagesToUpdate, userId, updateFrameworkRes);
if (updateFrameworkRes) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index fcd198e..2f69abf 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -738,6 +738,11 @@
private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
private long mLoweredFromNormalToVibrateTime;
+ // Uid of the active hotword detection service to check if caller is the one or not.
+ @GuardedBy("mHotwordDetectionServiceUidLock")
+ private int mHotwordDetectionServiceUid = android.os.Process.INVALID_UID;
+ private final Object mHotwordDetectionServiceUidLock = new Object();
+
// Array of Uids of valid accessibility services to check if caller is one of them
private final Object mAccessibilityServiceUidsLock = new Object();
@GuardedBy("mAccessibilityServiceUidsLock")
@@ -1339,6 +1344,9 @@
updateAssistantUId(true);
AudioSystem.setRttEnabled(mRttEnabled);
}
+ synchronized (mHotwordDetectionServiceUidLock) {
+ AudioSystem.setHotwordDetectionServiceUid(mHotwordDetectionServiceUid);
+ }
synchronized (mAccessibilityServiceUidsLock) {
AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
}
@@ -9082,6 +9090,16 @@
}
@Override
+ public void setHotwordDetectionServiceUid(int uid) {
+ synchronized (mHotwordDetectionServiceUidLock) {
+ if (mHotwordDetectionServiceUid != uid) {
+ mHotwordDetectionServiceUid = uid;
+ AudioSystem.setHotwordDetectionServiceUid(mHotwordDetectionServiceUid);
+ }
+ }
+ }
+
+ @Override
public void setAccessibilityServiceUids(IntArray uids) {
synchronized (mAccessibilityServiceUidsLock) {
if (uids.size() == 0) {
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index 973fbd2..6d56780 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -367,6 +367,14 @@
}
/**
+ * Same as {@link AudioSystem#setHotwordDetectionServiceUid(int)}
+ * Communicate UID of current HotwordDetectionService to audio policy service.
+ */
+ public int setHotwordDetectionServiceUid(int uid) {
+ return AudioSystem.setHotwordDetectionServiceUid(uid);
+ }
+
+ /**
* Same as {@link AudioSystem#setCurrentImeUid(int)}
* Communicate UID of current InputMethodService to audio policy service.
*/
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index afd1889..a0944c0 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -63,8 +63,6 @@
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayGroupListener;
import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
-import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
-import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
@@ -636,6 +634,9 @@
synchronized (mSyncRoot) {
final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
if (display != null) {
+ // Do not let constrain be overwritten by override from WindowManager.
+ info.shouldConstrainMetricsForLauncher =
+ display.getDisplayInfoLocked().shouldConstrainMetricsForLauncher;
if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
handleLogicalDisplayChangedLocked(display);
scheduleTraversalLocked(false);
@@ -1723,6 +1724,21 @@
}
}
+ void setShouldConstrainMetricsForLauncher(boolean constrain) {
+ // Apply constrain for every display.
+ synchronized (mSyncRoot) {
+ int[] displayIds = mLogicalDisplayMapper.getDisplayIdsLocked(Process.myUid());
+ for (int i : displayIds) {
+ final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(i);
+ if (display == null) {
+ return;
+ }
+ display.getDisplayInfoLocked().shouldConstrainMetricsForLauncher = constrain;
+ setDisplayInfoOverrideFromWindowManagerInternal(i, display.getDisplayInfoLocked());
+ }
+ }
+ }
+
private void clearViewportsLocked() {
mViewports.clear();
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index 48edb73..94e64f0 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -58,6 +58,8 @@
return setDisplayModeDirectorLoggingEnabled(false);
case "dwb-set-cct":
return setAmbientColorTemperatureOverride();
+ case "constrain-launcher-metrics":
+ return setConstrainLauncherMetrics();
default:
return handleDefaultCommands(cmd);
}
@@ -88,6 +90,9 @@
pw.println(" Disable display mode director logging.");
pw.println(" dwb-set-cct CCT");
pw.println(" Sets the ambient color temperature override to CCT (use -1 to disable).");
+ pw.println(" constrain-launcher-metrics [true|false]");
+ pw.println(" Sets if Display#getRealSize and getRealMetrics should be constrained for ");
+ pw.println(" Launcher.");
pw.println();
Intent.printIntentArgsHelp(pw , "");
}
@@ -150,4 +155,15 @@
mService.setAmbientColorTemperatureOverride(cct);
return 0;
}
+
+ private int setConstrainLauncherMetrics() {
+ String constrainText = getNextArg();
+ if (constrainText == null) {
+ getErrPrintWriter().println("Error: no value specified");
+ return 1;
+ }
+ boolean constrain = Boolean.parseBoolean(constrainText);
+ mService.setShouldConstrainMetricsForLauncher(constrain);
+ return 0;
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index b0ad118..803ba40 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -153,7 +153,7 @@
updateVoteLocked(displayId, priority, vote);
}
};
- mSensorObserver = new SensorObserver(context, ballotBox);
+ mSensorObserver = new SensorObserver(context, ballotBox, injector);
mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler());
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
mDeviceConfig = injector.getDeviceConfig();
@@ -2129,27 +2129,34 @@
}
}
- private static class SensorObserver implements ProximityActiveListener {
- private static final String PROXIMITY_SENSOR_NAME = null;
- private static final String PROXIMITY_SENSOR_TYPE = Sensor.STRING_TYPE_PROXIMITY;
+ private final class SensorObserver implements ProximityActiveListener,
+ DisplayManager.DisplayListener {
+ private final String mProximitySensorName = null;
+ private final String mProximitySensorType = Sensor.STRING_TYPE_PROXIMITY;
private final BallotBox mBallotBox;
private final Context mContext;
+ private final Injector mInjector;
private DisplayManager mDisplayManager;
private DisplayManagerInternal mDisplayManagerInternal;
private boolean mIsProxActive = false;
+ private final SparseBooleanArray mDozeStateByDisplay;
- SensorObserver(Context context, BallotBox ballotBox) {
+ SensorObserver(Context context, BallotBox ballotBox, Injector injector) {
mContext = context;
mBallotBox = ballotBox;
+ mInjector = injector;
+ mDozeStateByDisplay = new SparseBooleanArray();
}
@Override
public void onProximityActive(boolean isActive) {
- if (mIsProxActive != isActive) {
- mIsProxActive = isActive;
- recalculateVotes();
+ synchronized (mLock) {
+ if (mIsProxActive != isActive) {
+ mIsProxActive = isActive;
+ recalculateVotesLocked();
+ }
}
}
@@ -2160,17 +2167,27 @@
final SensorManagerInternal sensorManager =
LocalServices.getService(SensorManagerInternal.class);
sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this);
+
+ synchronized (mLock) {
+ for (Display d : mDisplayManager.getDisplays()) {
+ mDozeStateByDisplay.put(d.getDisplayId(), mInjector.isDozeState(d));
+ }
+ }
+ mInjector.registerDisplayListener(this, BackgroundThread.getHandler(),
+ DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
}
- private void recalculateVotes() {
+ private void recalculateVotesLocked() {
final Display[] displays = mDisplayManager.getDisplays();
for (Display d : displays) {
int displayId = d.getDisplayId();
Vote vote = null;
- if (mIsProxActive) {
+ if (mIsProxActive && !mDozeStateByDisplay.get(displayId)) {
final RefreshRateRange rate =
mDisplayManagerInternal.getRefreshRateForDisplayAndSensor(
- displayId, PROXIMITY_SENSOR_NAME, PROXIMITY_SENSOR_TYPE);
+ displayId, mProximitySensorName, mProximitySensorType);
if (rate != null) {
vote = Vote.forRefreshRates(rate.min, rate.max);
}
@@ -2182,6 +2199,41 @@
void dumpLocked(PrintWriter pw) {
pw.println(" SensorObserver");
pw.println(" mIsProxActive=" + mIsProxActive);
+ pw.println(" mDozeStateByDisplay:");
+ for (int i = 0; i < mDozeStateByDisplay.size(); i++) {
+ final int id = mDozeStateByDisplay.keyAt(i);
+ final boolean dozed = mDozeStateByDisplay.valueAt(i);
+ pw.println(" " + id + " -> " + dozed);
+ }
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ boolean isDozeState = mInjector.isDozeState(mDisplayManager.getDisplay(displayId));
+ synchronized (mLock) {
+ mDozeStateByDisplay.put(displayId, isDozeState);
+ recalculateVotesLocked();
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ boolean wasDozeState = mDozeStateByDisplay.get(displayId);
+ synchronized (mLock) {
+ mDozeStateByDisplay.put(displayId,
+ mInjector.isDozeState(mDisplayManager.getDisplay(displayId)));
+ if (wasDozeState != mDozeStateByDisplay.get(displayId)) {
+ recalculateVotesLocked();
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ synchronized (mLock) {
+ mDozeStateByDisplay.delete(displayId);
+ recalculateVotesLocked();
+ }
}
}
@@ -2413,6 +2465,8 @@
Handler handler, long flags);
BrightnessInfo getBrightnessInfo(int displayId);
+
+ boolean isDozeState(Display d);
}
@VisibleForTesting
@@ -2465,6 +2519,11 @@
return null;
}
+ @Override
+ public boolean isDozeState(Display d) {
+ return Display.isDozeState(d.getState());
+ }
+
private DisplayManager getDisplayManager() {
if (mDisplayManager == null) {
mDisplayManager = mContext.getSystemService(DisplayManager.class);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 5186744..86c9ca9 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -233,6 +233,8 @@
info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
info.roundedCorners = mOverrideDisplayInfo.roundedCorners;
+ info.shouldConstrainMetricsForLauncher =
+ mOverrideDisplayInfo.shouldConstrainMetricsForLauncher;
}
mInfo.set(info);
}
diff --git a/services/core/java/com/android/server/hdmi/RequestSadAction.java b/services/core/java/com/android/server/hdmi/RequestSadAction.java
new file mode 100644
index 0000000..4d36078
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestSadAction.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2021 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.hdmi;
+
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Feature action that queries the Short Audio Descriptor (SAD) of another device. This action is
+ * initiated from the Android system working as TV device to get the SAD of the connected audio
+ * system device.
+ * <p>
+ * Package-private
+ */
+final class RequestSadAction extends HdmiCecFeatureAction {
+ private static final String TAG = "RequestSadAction";
+
+ // State in which the action is waiting for <Report Short Audio Descriptor>.
+ private static final int STATE_WAITING_FOR_REPORT_SAD = 1;
+
+ private static final List<Integer> ALL_CEC_CODECS = new ArrayList<Integer>(Arrays.asList(
+ Constants.AUDIO_CODEC_LPCM,
+ Constants.AUDIO_CODEC_DD,
+ Constants.AUDIO_CODEC_MPEG1,
+ Constants.AUDIO_CODEC_MP3,
+ Constants.AUDIO_CODEC_MPEG2,
+ Constants.AUDIO_CODEC_AAC,
+ Constants.AUDIO_CODEC_DTS,
+ Constants.AUDIO_CODEC_ATRAC,
+ Constants.AUDIO_CODEC_ONEBITAUDIO,
+ Constants.AUDIO_CODEC_DDP,
+ Constants.AUDIO_CODEC_DTSHD,
+ Constants.AUDIO_CODEC_TRUEHD,
+ Constants.AUDIO_CODEC_DST,
+ Constants.AUDIO_CODEC_WMAPRO,
+ Constants.AUDIO_CODEC_MAX));
+ private static final int MAX_SAD_PER_REQUEST = 4;
+ private static final int RETRY_COUNTER_MAX = 1;
+ private final int mTargetAddress;
+ private final RequestSadCallback mCallback;
+ // List of all valid SADs reported by the target device. Not parsed nor deduplicated.
+ private final List<byte[]> mSupportedSads = new ArrayList<>();
+ private int mQueriedSadCount = 0; // Number of SADs queries that has already been completed
+ private int mTimeoutRetry = 0; // Number of times we have already retried on time-out
+
+ /**
+ * Constructor.
+ *
+ * @param source an instance of {@link HdmiCecLocalDevice}.
+ * @param targetAddress the logical address the SAD is directed at.
+ */
+ RequestSadAction(HdmiCecLocalDevice source, int targetAddress, RequestSadCallback callback) {
+ super(source);
+ mTargetAddress = targetAddress;
+ mCallback = Objects.requireNonNull(callback);
+ }
+
+
+ @Override
+ boolean start() {
+ querySad();
+ return true;
+ }
+
+ private void querySad() {
+ if (mQueriedSadCount >= ALL_CEC_CODECS.size()) {
+ wrapUpAndFinish();
+ return;
+ }
+ int[] codecsToQuery = ALL_CEC_CODECS.subList(mQueriedSadCount,
+ Math.min(ALL_CEC_CODECS.size(), mQueriedSadCount + MAX_SAD_PER_REQUEST))
+ .stream().mapToInt(i -> i).toArray();
+ sendCommand(HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(getSourceAddress(),
+ mTargetAddress, codecsToQuery));
+ mState = STATE_WAITING_FOR_REPORT_SAD;
+ addTimer(mState, HdmiConfig.TIMEOUT_MS);
+ }
+
+ @Override
+ boolean processCommand(HdmiCecMessage cmd) {
+ if (mState != STATE_WAITING_FOR_REPORT_SAD
+ || mTargetAddress != cmd.getSource()) {
+ return false;
+ }
+ if (cmd.getOpcode() == Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR) {
+ if (cmd.getParams() == null || cmd.getParams().length == 0
+ || cmd.getParams().length % 3 != 0) {
+ // Invalid message. Wait for time-out and query again.
+ return true;
+ }
+ for (int i = 0; i < cmd.getParams().length - 2; i += 3) {
+ if (isValidCodec(cmd.getParams()[i])) {
+ byte[] sad = new byte[]{cmd.getParams()[i], cmd.getParams()[i + 1],
+ cmd.getParams()[i + 2]};
+ updateResult(sad);
+ }
+ // Don't include invalid codecs in the result. Don't query again.
+ Slog.w(TAG, "Received invalid codec " + cmd.getParams()[i] + ".");
+ }
+ mQueriedSadCount += MAX_SAD_PER_REQUEST;
+ mTimeoutRetry = 0;
+ querySad();
+ return true;
+ }
+ if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
+ && (cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR
+ && (cmd.getParams()[1] & 0xFF) == Constants.ABORT_INVALID_OPERAND) {
+ // Queried SADs are not supported
+ mQueriedSadCount += MAX_SAD_PER_REQUEST;
+ mTimeoutRetry = 0;
+ querySad();
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isValidCodec(byte codec) {
+ return Constants.AUDIO_CODEC_NONE < (codec & 0xFF)
+ && (codec & 0xFF) <= Constants.AUDIO_CODEC_MAX;
+ }
+
+ private void updateResult(byte[] sad) {
+ mSupportedSads.add(sad);
+ }
+
+ @Override
+ void handleTimerEvent(int state) {
+ if (mState != state) {
+ return;
+ }
+ if (state == STATE_WAITING_FOR_REPORT_SAD) {
+ if (++mTimeoutRetry <= RETRY_COUNTER_MAX) {
+ querySad();
+ return;
+ }
+ mQueriedSadCount += MAX_SAD_PER_REQUEST;
+ mTimeoutRetry = 0;
+ querySad();
+ }
+ }
+
+ private void wrapUpAndFinish() {
+ mCallback.onRequestSadDone(mSupportedSads);
+ finish();
+ }
+
+ /**
+ * Interface used to report result of SAD request.
+ */
+ interface RequestSadCallback {
+ /**
+ * Called when SAD request is done.
+ *
+ * @param sads a list of all supported SADs. It can be an empty list.
+ */
+ void onRequestSadDone(List<byte[]> supportedSads);
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index c553176..c905fe0 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -180,7 +180,7 @@
private static final boolean UNTRUSTED_TOUCHES_TOAST = false;
public static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
- SystemProperties.getBoolean("persist.debug.per_window_input_rotation", true);
+ SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
// Pointer to native input manager service object.
private final long mPtr;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 87982cd..bff7e52 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1237,15 +1237,19 @@
}
@Override
- public MediaSession.Token getMediaKeyEventSession() {
+ public MediaSession.Token getMediaKeyEventSession(ComponentName notificationListener) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+ final int userId = userHandle.getIdentifier();
final long token = Binder.clearCallingIdentity();
try {
- if (!hasMediaControlPermission(pid, uid)) {
- throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
- + " get the media key event session");
+ if (!hasMediaControlPermission(pid, uid)
+ && !isEnabledNotificationListener(
+ notificationListener, userHandle, userId)) {
+ throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
+ + " notification listener is required to"
+ + " get media key event session.");
}
MediaSessionRecordImpl record;
synchronized (mLock) {
@@ -1268,15 +1272,19 @@
}
@Override
- public String getMediaKeyEventSessionPackageName() {
+ public String getMediaKeyEventSessionPackageName(ComponentName notificationListener) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+ final int userId = userHandle.getIdentifier();
final long token = Binder.clearCallingIdentity();
try {
- if (!hasMediaControlPermission(pid, uid)) {
- throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
- + " get the media key event session package");
+ if (!hasMediaControlPermission(pid, uid)
+ && !isEnabledNotificationListener(
+ notificationListener, userHandle, userId)) {
+ throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
+ + " notification listener is required to"
+ + " get media key event session package name");
}
MediaSessionRecordImpl record;
synchronized (mLock) {
@@ -1588,19 +1596,25 @@
@Override
public void addOnMediaKeyEventSessionChangedListener(
- final IOnMediaKeyEventSessionChangedListener listener) {
+ final IOnMediaKeyEventSessionChangedListener listener,
+ final ComponentName notificationListener) {
if (listener == null) {
- Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: lister is null, ignoring");
+ Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: listener is null, ignoring");
return;
}
+
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+ final int userId = userHandle.getIdentifier();
final long token = Binder.clearCallingIdentity();
try {
- if (!hasMediaControlPermission(pid, uid)) {
- throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
- + " add MediaKeyEventSessionChangedListener");
+ if (!hasMediaControlPermission(pid, uid)
+ && !isEnabledNotificationListener(
+ notificationListener, userHandle, userId)) {
+ throw new SecurityException("MEDIA_CONTENT_CONTROL permission or an enabled"
+ + " notification listener is required to"
+ + " add MediaKeyEventSessionChangedListener.");
}
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1622,18 +1636,16 @@
public void removeOnMediaKeyEventSessionChangedListener(
final IOnMediaKeyEventSessionChangedListener listener) {
if (listener == null) {
- Log.w(TAG, "removeOnMediaKeyEventSessionChangedListener: lister is null, ignoring");
+ Log.w(TAG, "removeOnMediaKeyEventSessionChangedListener: listener is null,"
+ + " ignoring");
return;
}
+
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
final long token = Binder.clearCallingIdentity();
try {
- if (!hasMediaControlPermission(pid, uid)) {
- throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
- + " remove MediaKeyEventSessionChangedListener");
- }
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null || user.mFullUserId != userId) {
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 6ae4dd0..7889ff2 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -250,6 +250,14 @@
throws PackageManagerException;
/**
+ * Returns {@code ApeInfo} about apex sessions that have been marked ready via
+ * {@link #markStagedSessionReady(int)}
+ *
+ * Returns empty array if there is no staged apex session or if there is any error.
+ */
+ abstract ApexInfo[] getStagedApexInfos(ApexSessionParams params);
+
+ /**
* Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
* applied at next reboot.
*
@@ -758,6 +766,19 @@
}
@Override
+ ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
+ try {
+ return waitForApexService().getStagedApexInfos(params);
+ } catch (RemoteException re) {
+ Slog.w(TAG, "Unable to contact apexservice" + re.getMessage());
+ throw new RuntimeException(re);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to collect staged apex infos" + e.getMessage());
+ return new ApexInfo[0];
+ }
+ }
+
+ @Override
void markStagedSessionReady(int sessionId) throws PackageManagerException {
try {
waitForApexService().markStagedSessionReady(sessionId);
@@ -1250,6 +1271,11 @@
}
@Override
+ ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
void markStagedSessionReady(int sessionId) {
throw new UnsupportedOperationException();
}
diff --git a/services/core/java/com/android/server/pm/InstallParams.java b/services/core/java/com/android/server/pm/InstallParams.java
index e87dbed..45ce3980 100644
--- a/services/core/java/com/android/server/pm/InstallParams.java
+++ b/services/core/java/com/android/server/pm/InstallParams.java
@@ -1207,7 +1207,10 @@
// Check for shared user id changes
String invalidPackageName = null;
if (!Objects.equals(oldPackage.getSharedUserId(),
- parsedPackage.getSharedUserId())) {
+ parsedPackage.getSharedUserId())
+ // Don't mark as invalid if the app is trying to
+ // leave a sharedUserId
+ && parsedPackage.getSharedUserId() != null) {
invalidPackageName = parsedPackage.getPackageName();
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c9e4829..d2c15ab 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -289,6 +289,7 @@
import android.util.PackageUtils;
import android.util.Pair;
import android.util.PrintStreamPrinter;
+import android.util.Printer;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -327,6 +328,7 @@
import com.android.server.DeviceIdleInternal;
import com.android.server.EventLogTags;
import com.android.server.FgThread;
+import com.android.server.IntentResolver;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.PackageWatchdog;
@@ -701,6 +703,20 @@
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
private static final long ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES = 142191088;
+ /**
+ * Components of apps targeting Android T and above will stop receiving intents from
+ * external callers that do not match its declared intent filters.
+ *
+ * When an app registers an exported component in its manifest and adds an <intent-filter>,
+ * the component can be started by any intent - even those that do not match the intent filter.
+ * This has proven to be something that many developers find counterintuitive.
+ * Without checking the intent when the component is started, in some circumstances this can
+ * allow 3P apps to trigger internal-only functionality.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
+ private static final long ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS = 161252188;
+
public static final String PLATFORM_PACKAGE_NAME = "android";
static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
@@ -2160,9 +2176,11 @@
false /* requireFullPermission */, false /* checkShell */,
"query intent activities");
final String pkgName = intent.getPackage();
+ Intent originalIntent = null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
+ originalIntent = intent;
intent = intent.getSelector();
comp = intent.getComponent();
}
@@ -2172,8 +2190,9 @@
comp != null || pkgName != null /*onlyExposedExplicitly*/,
isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
flags));
+ List<ResolveInfo> list = Collections.emptyList();
+ boolean skipPostResolution = false;
if (comp != null) {
- final List<ResolveInfo> list = new ArrayList<>(1);
final ActivityInfo ai = getActivityInfo(comp, flags, userId);
if (ai != null) {
// When specifying an explicit component, we prevent the activity from being
@@ -2216,35 +2235,45 @@
if (!blockInstantResolution && !blockNormalResolution) {
final ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
+ list = new ArrayList<>(1);
list.add(ri);
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, intent, resolvedType, filterCallingUid);
}
}
-
- return applyPostResolutionFilter(
- list, instantAppPkgName, allowDynamicSplits, filterCallingUid,
- resolveForStart,
- userId, intent);
+ } else {
+ QueryIntentActivitiesResult lockedResult =
+ queryIntentActivitiesInternalBody(
+ intent, resolvedType, flags, filterCallingUid, userId,
+ resolveForStart, allowDynamicSplits, pkgName, instantAppPkgName);
+ if (lockedResult.answer != null) {
+ skipPostResolution = true;
+ list = lockedResult.answer;
+ } else {
+ if (lockedResult.addInstant) {
+ String callingPkgName = getInstantAppPackageName(filterCallingUid);
+ boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
+ lockedResult.result = maybeAddInstantAppInstaller(
+ lockedResult.result, intent, resolvedType, flags,
+ userId, resolveForStart, isRequesterInstantApp);
+ }
+ if (lockedResult.sortResult) {
+ lockedResult.result.sort(RESOLVE_PRIORITY_SORTER);
+ }
+ list = lockedResult.result;
+ }
}
- QueryIntentActivitiesResult lockedResult =
- queryIntentActivitiesInternalBody(
- intent, resolvedType, flags, filterCallingUid, userId, resolveForStart,
- allowDynamicSplits, pkgName, instantAppPkgName);
- if (lockedResult.answer != null) {
- return lockedResult.answer;
+ if (originalIntent != null) {
+ // We also have to ensure all components match the original intent
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, originalIntent, resolvedType, filterCallingUid);
}
- if (lockedResult.addInstant) {
- String callingPkgName = getInstantAppPackageName(filterCallingUid);
- boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
- lockedResult.result = maybeAddInstantAppInstaller(lockedResult.result, intent,
- resolvedType, flags, userId, resolveForStart, isRequesterInstantApp);
- }
- if (lockedResult.sortResult) {
- Collections.sort(lockedResult.result, RESOLVE_PRIORITY_SORTER);
- }
- return applyPostResolutionFilter(
- lockedResult.result, instantAppPkgName, allowDynamicSplits, filterCallingUid,
+ return skipPostResolution ? list : applyPostResolutionFilter(
+ list, instantAppPkgName, allowDynamicSplits, filterCallingUid,
resolveForStart, userId, intent);
}
@@ -2267,15 +2296,17 @@
final String instantAppPkgName = getInstantAppPackageName(callingUid);
flags = updateFlagsForResolve(flags, userId, callingUid, includeInstantApps,
false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
+ Intent originalIntent = null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
+ originalIntent = intent;
intent = intent.getSelector();
comp = intent.getComponent();
}
}
+ List<ResolveInfo> list = Collections.emptyList();
if (comp != null) {
- final List<ResolveInfo> list = new ArrayList<>(1);
final ServiceInfo si = getServiceInfo(comp, flags, userId);
if (si != null) {
// When specifying an explicit component, we prevent the service from being
@@ -2308,14 +2339,26 @@
if (!blockInstantResolution && !blockNormalResolution) {
final ResolveInfo ri = new ResolveInfo();
ri.serviceInfo = si;
+ list = new ArrayList<>(1);
list.add(ri);
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, intent, resolvedType, callingUid);
}
}
- return list;
+ } else {
+ list = queryIntentServicesInternalBody(intent, resolvedType, flags,
+ userId, callingUid, instantAppPkgName);
}
- return queryIntentServicesInternalBody(intent, resolvedType, flags,
- userId, callingUid, instantAppPkgName);
+ if (originalIntent != null) {
+ // We also have to ensure all components match the original intent
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, originalIntent, resolvedType, callingUid);
+ }
+
+ return list;
}
protected @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
@@ -5544,10 +5587,8 @@
}
}
}
- private static final ThreadLocal<ThreadComputer> sThreadComputer = new ThreadLocal<>() {
- @Override protected ThreadComputer initialValue() {
- return new ThreadComputer();
- }};
+ private static final ThreadLocal<ThreadComputer> sThreadComputer =
+ ThreadLocal.withInitial(ThreadComputer::new);
/**
* This lock is used to make reads from {@link #sSnapshotInvalid} and
@@ -8136,7 +8177,7 @@
final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+ UserHandle.USER_SYSTEM, Binder.getCallingUid());
if (matches.size() == 1) {
return matches.get(0).getComponentInfo().packageName;
} else if (matches.size() == 0) {
@@ -8232,7 +8273,7 @@
final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+ UserHandle.USER_SYSTEM, Binder.getCallingUid());
ResolveInfo best = null;
final int N = matches.size();
for (int i = 0; i < N; i++) {
@@ -8260,7 +8301,7 @@
Intent intent = new Intent(Intent.ACTION_DOMAINS_NEED_VERIFICATION);
List<ResolveInfo> matches = queryIntentReceiversInternal(intent, null,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+ UserHandle.USER_SYSTEM, Binder.getCallingUid());
ResolveInfo best = null;
final int N = matches.size();
for (int i = 0; i < N; i++) {
@@ -10939,30 +10980,32 @@
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
String resolvedType, int flags, int userId) {
- return new ParceledListSlice<>(
- queryIntentReceiversInternal(intent, resolvedType, flags, userId,
- false /*allowDynamicSplits*/));
+ return new ParceledListSlice<>(queryIntentReceiversInternal(intent, resolvedType,
+ flags, userId, Binder.getCallingUid()));
}
+ // In this method, we have to know the actual calling UID, but in some cases Binder's
+ // call identity is removed, so the UID has to be passed in explicitly.
private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
- String resolvedType, int flags, int userId, boolean allowDynamicSplits) {
+ String resolvedType, int flags, int userId, int filterCallingUid) {
if (!mUserManager.exists(userId)) return Collections.emptyList();
- final int callingUid = Binder.getCallingUid();
- enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
+ enforceCrossUserPermission(filterCallingUid, userId, false /*requireFullPermission*/,
false /*checkShell*/, "query intent receivers");
- final String instantAppPkgName = getInstantAppPackageName(callingUid);
- flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
+ final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
+ flags = updateFlagsForResolve(flags, userId, filterCallingUid, false /*includeInstantApps*/,
isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
flags));
+ Intent originalIntent = null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
+ originalIntent = intent;
intent = intent.getSelector();
comp = intent.getComponent();
}
}
+ List<ResolveInfo> list = Collections.emptyList();
if (comp != null) {
- final List<ResolveInfo> list = new ArrayList<>(1);
final ActivityInfo ai = getReceiverInfo(comp, flags, userId);
if (ai != null) {
// When specifying an explicit component, we prevent the activity from being
@@ -10998,40 +11041,44 @@
if (!blockResolution) {
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
+ list = new ArrayList<>(1);
list.add(ri);
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, true, intent, resolvedType, filterCallingUid);
}
}
- return applyPostResolutionFilter(
- list, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
- intent);
+ } else {
+ // reader
+ synchronized (mLock) {
+ String pkgName = intent.getPackage();
+ if (pkgName == null) {
+ final List<ResolveInfo> result =
+ mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
+ if (result != null) {
+ list = result;
+ }
+ }
+ final AndroidPackage pkg = mPackages.get(pkgName);
+ if (pkg != null) {
+ final List<ResolveInfo> result = mComponentResolver.queryReceivers(
+ intent, resolvedType, flags, pkg.getReceivers(), userId);
+ if (result != null) {
+ list = result;
+ }
+ }
+ }
}
- // reader
- synchronized (mLock) {
- String pkgName = intent.getPackage();
- if (pkgName == null) {
- final List<ResolveInfo> result =
- mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
- if (result == null) {
- return Collections.emptyList();
- }
- return applyPostResolutionFilter(
- result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
- intent);
- }
- final AndroidPackage pkg = mPackages.get(pkgName);
- if (pkg != null) {
- final List<ResolveInfo> result = mComponentResolver.queryReceivers(
- intent, resolvedType, flags, pkg.getReceivers(), userId);
- if (result == null) {
- return Collections.emptyList();
- }
- return applyPostResolutionFilter(
- result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
- intent);
- }
- return Collections.emptyList();
+ if (originalIntent != null) {
+ // We also have to ensure all components match the original intent
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, true, originalIntent, resolvedType, filterCallingUid);
}
+
+ return applyPostResolutionFilter(
+ list, instantAppPkgName, false, filterCallingUid, false, userId, intent);
}
@Override
@@ -11073,6 +11120,68 @@
includeInstantApps);
}
+ // Static to give access to ComputeEngine
+ private static void applyEnforceIntentFilterMatching(
+ PlatformCompat compat, ComponentResolver resolver,
+ List<ResolveInfo> resolveInfos, boolean isReceiver,
+ Intent intent, String resolvedType, int filterCallingUid) {
+ // Do not enforce filter matching when the caller is system or root.
+ // see ActivityManager#checkComponentPermission(String, int, int, boolean)
+ if (filterCallingUid == Process.ROOT_UID || filterCallingUid == Process.SYSTEM_UID) {
+ return;
+ }
+
+ final Printer logPrinter = DEBUG_INTENT_MATCHING
+ ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM)
+ : null;
+
+ for (int i = resolveInfos.size() - 1; i >= 0; --i) {
+ final ComponentInfo info = resolveInfos.get(i).getComponentInfo();
+
+ // Do not enforce filter matching when the caller is the same app
+ if (info.applicationInfo.uid == filterCallingUid) {
+ continue;
+ }
+
+ // Only enforce filter matching if target app's target SDK >= T
+ if (!compat.isChangeEnabledInternal(
+ ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS, info.applicationInfo)) {
+ continue;
+ }
+
+ final ParsedMainComponent comp;
+ if (info instanceof ActivityInfo) {
+ if (isReceiver) {
+ comp = resolver.getReceiver(info.getComponentName());
+ } else {
+ comp = resolver.getActivity(info.getComponentName());
+ }
+ } else if (info instanceof ServiceInfo) {
+ comp = resolver.getService(info.getComponentName());
+ } else {
+ // This shall never happen
+ throw new IllegalArgumentException("Unsupported component type");
+ }
+
+ if (comp.getIntents().isEmpty()) {
+ continue;
+ }
+
+ final boolean match = comp.getIntents().stream().anyMatch(
+ f -> IntentResolver.intentMatchesFilter(f, intent, resolvedType));
+ if (!match) {
+ Slog.w(TAG, "Intent does not match component's intent filter: " + intent);
+ Slog.w(TAG, "Access blocked: " + comp.getComponentName());
+ if (DEBUG_INTENT_MATCHING) {
+ Slog.v(TAG, "Component intent filters:");
+ comp.getIntents().forEach(f -> f.dump(logPrinter, " "));
+ Slog.v(TAG, "-----------------------------");
+ }
+ resolveInfos.remove(i);
+ }
+ }
+ }
+
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
String resolvedType, int flags, int userId) {
@@ -13528,10 +13637,6 @@
}
}
-
-
-
-
/**
* Returns the actual scan flags depending upon the state of the other settings.
* <p>Updated system applications will not have the following flags set
@@ -13699,10 +13804,10 @@
*/
boolean optimisticallyRegisterAppId(@NonNull ScanResult result)
throws PackageManagerException {
- if (!result.mExistingSettingCopied) {
+ if (!result.mExistingSettingCopied || result.mNeedsNewAppId) {
// THROWS: when we can't allocate a user id. add call to check if there's
// enough space to ensure we won't throw; otherwise, don't modify state
- return mSettings.registerAppIdLPw(result.mPkgSetting);
+ return mSettings.registerAppIdLPw(result.mPkgSetting, result.mNeedsNewAppId);
}
return false;
}
@@ -14072,15 +14177,25 @@
}
}
+ boolean leavingSharedUser = false;
+
if (pkgSetting != null && pkgSetting.sharedUser != sharedUserSetting) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Package " + parsedPackage.getPackageName() + " shared user changed from "
- + (pkgSetting.sharedUser != null
- ? pkgSetting.sharedUser.name : "<nothing>")
- + " to "
- + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
- + "; replacing with new");
- pkgSetting = null;
+ if (pkgSetting.sharedUser != null && sharedUserSetting == null) {
+ leavingSharedUser = true;
+ // Log that something is leaving shareduid and keep going
+ Slog.i(TAG,
+ "Package " + parsedPackage.getPackageName() + " shared user changed from "
+ + pkgSetting.sharedUser.name + " to " + "<nothing>.");
+ } else {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Package " + parsedPackage.getPackageName() + " shared user changed from "
+ + (pkgSetting.sharedUser != null
+ ? pkgSetting.sharedUser.name : "<nothing>")
+ + " to "
+ + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
+ + "; replacing with new");
+ pkgSetting = null;
+ }
}
String[] usesStaticLibraries = null;
@@ -14356,7 +14471,8 @@
}
return new ScanResult(request, true, pkgSetting, changedAbiCodePath,
- !createNewPackage /* existingSettingCopied */, staticSharedLibraryInfo,
+ !createNewPackage /* existingSettingCopied */,
+ leavingSharedUser /* needsNewAppId */, staticSharedLibraryInfo,
dynamicSharedLibraryInfos);
}
@@ -21735,6 +21851,10 @@
continue;
}
+ // TODO@ashfall check ScanResult.mNeedsNewAppId, and if true instead
+ // of creating app data, migrate / change ownership of existing
+ // data.
+
if (ps.getInstalled(user.id)) {
// TODO: when user data is locked, mark that we're still dirty
prepareAppData(batch, pkg, user.id, flags).thenRun(() -> {
@@ -22399,7 +22519,7 @@
}
boolean readPermissionStateForUser(@UserIdInt int userId) {
- synchronized (mPackages) {
+ synchronized (mLock) {
mPermissionManager.writeLegacyPermissionStateTEMP();
mSettings.readPermissionStateForUserSyncLPr(userId);
mPermissionManager.readLegacyPermissionStateTEMP();
@@ -22471,7 +22591,7 @@
if (packageName == null || alias == null) {
return null;
}
- synchronized(mLock) {
+ synchronized (mLock) {
final AndroidPackage pkg = mPackages.get(packageName);
if (pkg == null
|| shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()),
@@ -22518,7 +22638,7 @@
if (packageName == null || ks == null) {
return false;
}
- synchronized(mLock) {
+ synchronized (mLock) {
final AndroidPackage pkg = mPackages.get(packageName);
if (pkg == null
|| shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()),
@@ -23401,6 +23521,13 @@
}
@Override
+ public List<ResolveInfo> queryIntentReceivers(Intent intent,
+ String resolvedType, int flags, int filterCallingUid, int userId) {
+ return PackageManagerService.this.queryIntentReceiversInternal(intent, resolvedType,
+ flags, userId, filterCallingUid);
+ }
+
+ @Override
public List<ResolveInfo> queryIntentServices(
Intent intent, int flags, int callingUid, int userId) {
final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
diff --git a/services/core/java/com/android/server/pm/ScanResult.java b/services/core/java/com/android/server/pm/ScanResult.java
index 6915a50..34f86ba 100644
--- a/services/core/java/com/android/server/pm/ScanResult.java
+++ b/services/core/java/com/android/server/pm/ScanResult.java
@@ -36,6 +36,11 @@
*/
public final boolean mExistingSettingCopied;
/**
+ * Whether or not the original PackageSetting needs to be updated with
+ * a new uid. Useful when leaving a sharedUserID.
+ */
+ public final boolean mNeedsNewAppId;
+ /**
* The final package settings. This may be the same object passed in
* the {@link ScanRequest}, but, with modified values.
*/
@@ -52,6 +57,7 @@
ScanRequest request, boolean success,
@Nullable PackageSetting pkgSetting,
@Nullable List<String> changedAbiCodePath, boolean existingSettingCopied,
+ boolean needsNewAppId,
SharedLibraryInfo staticSharedLibraryInfo,
List<SharedLibraryInfo> dynamicSharedLibraryInfos) {
mRequest = request;
@@ -59,6 +65,7 @@
mPkgSetting = pkgSetting;
mChangedAbiCodePath = changedAbiCodePath;
mExistingSettingCopied = existingSettingCopied;
+ mNeedsNewAppId = needsNewAppId;
mStaticSharedLibraryInfo = staticSharedLibraryInfo;
mDynamicSharedLibraryInfos = dynamicSharedLibraryInfos;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 3995cc6..902263a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1126,9 +1126,9 @@
* already registered.
* @throws PackageManagerException If a user ID could not be allocated.
*/
- boolean registerAppIdLPw(PackageSetting p) throws PackageManagerException {
+ boolean registerAppIdLPw(PackageSetting p, boolean forceNew) throws PackageManagerException {
final boolean createdNew;
- if (p.appId == 0) {
+ if (p.appId == 0 || forceNew) {
// Assign new user ID
p.appId = acquireAndRegisterNewAppIdLPw(p);
createdNew = true;
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index 3eb4bde..2fcc4b2 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -55,6 +55,7 @@
*/
public final class PackageImpl extends ParsingPackageImpl implements ParsedPackage, AndroidPackage {
+ @NonNull
public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
@NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp) {
return new PackageImpl(packageName, baseCodePath, codePath, manifestArray, isCoreApp);
@@ -70,6 +71,7 @@
* this case only cares about
* volumeUuid, just fake it rather than having separate method paths.
*/
+ @NonNull
public static AndroidPackage buildFakeForDeletion(String packageName, String volumeUuid) {
return ((ParsedPackage) PackageImpl.forTesting(packageName)
.setVolumeUuid(volumeUuid)
@@ -77,11 +79,13 @@
.hideAsFinal();
}
+ @NonNull
@VisibleForTesting
public static ParsingPackage forTesting(String packageName) {
return forTesting(packageName, "");
}
+ @NonNull
@VisibleForTesting
public static ParsingPackage forTesting(String packageName, String baseCodePath) {
return new PackageImpl(packageName, baseCodePath, baseCodePath, null, false);
@@ -568,6 +572,7 @@
assignDerivedFields();
}
+ @NonNull
public static final Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() {
@Override
public PackageImpl createFromParcel(Parcel source) {
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index e85fa23..0f4f58b 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -228,17 +228,20 @@
Vibration.Status status = null;
while (!mStepQueue.isEmpty()) {
- long waitTime = mStepQueue.calculateWaitTime();
- if (waitTime <= 0) {
- mStepQueue.consumeNext();
- } else {
- synchronized (mLock) {
+ long waitTime;
+ synchronized (mLock) {
+ waitTime = mStepQueue.calculateWaitTime();
+ if (waitTime > 0) {
try {
mLock.wait(waitTime);
} catch (InterruptedException e) {
}
}
}
+ // If we waited, the queue may have changed, so let the loop run again.
+ if (waitTime <= 0) {
+ mStepQueue.consumeNext();
+ }
Vibration.Status currentStatus = mStop ? Vibration.Status.CANCELLED
: mStepQueue.calculateVibrationStatus(sequentialEffectSize);
if (status == null && currentStatus != Vibration.Status.RUNNING) {
@@ -387,15 +390,13 @@
}
/** Returns the time in millis to wait before calling {@link #consumeNext()}. */
+ @GuardedBy("mLock")
public long calculateWaitTime() {
- Step nextStep;
- synchronized (mLock) {
- if (!mPendingOnVibratorCompleteSteps.isEmpty()) {
- // Steps anticipated by vibrator complete callback should be played right away.
- return 0;
- }
- nextStep = mNextSteps.peek();
+ if (!mPendingOnVibratorCompleteSteps.isEmpty()) {
+ // Steps anticipated by vibrator complete callback should be played right away.
+ return 0;
}
+ Step nextStep = mNextSteps.peek();
return nextStep == null ? 0 : nextStep.calculateWaitTime();
}
@@ -603,7 +604,10 @@
return false;
}
- /** Returns the time in millis to wait before playing this step. */
+ /**
+ * Returns the time in millis to wait before playing this step. This is performed
+ * while holding the queue lock, so should not rely on potentially slow operations.
+ */
public long calculateWaitTime() {
if (startTime == Long.MAX_VALUE) {
// This step don't have a predefined start time, it's just marked to be executed
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 331b8de..675c7eb 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1197,10 +1197,10 @@
final Task task = r.getTask();
isLastRunningActivity = task.topRunningActivity() == r;
- final Intent baseIntent = task.getBaseIntent();
- final boolean activityIsBaseActivity = baseIntent != null
- && r.mActivityComponent.equals(baseIntent.getComponent());
- baseActivityIntent = activityIsBaseActivity ? r.intent : null;
+
+ final boolean isBaseActivity = r.mActivityComponent.equals(task.realActivity);
+ baseActivityIntent = isBaseActivity ? r.intent : null;
+
launchedFromHome = r.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e6e18fd..37003ad 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3687,7 +3687,7 @@
@Override
void removeImmediately() {
- if (!finishing) {
+ if (!isState(DESTROYING, DESTROYED)) {
// If Task#removeImmediately is called directly with alive activities, ensure that the
// activities are destroyed and detached from process.
destroyImmediately("removeImmediately");
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 25827cf..19cf14f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1908,15 +1908,15 @@
if (r.moveFocusableActivityToTop("setFocusedTask")) {
mRootWindowContainer.resumeFocusedTasksTopActivities();
- } else if (touchedActivity != null && touchedActivity != r
- && touchedActivity.getTask() == r.getTask()
- && touchedActivity.getTaskFragment() != r.getTaskFragment()) {
- // Set the focused app directly since the focused window is not on the
- // top-most TaskFragment of the top-most Task
- final DisplayContent displayContent = touchedActivity.getDisplayContent();
- displayContent.setFocusedApp(touchedActivity);
- mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
- true /* updateInputWindows */);
+ } else if (touchedActivity != null && touchedActivity.isFocusable()) {
+ final TaskFragment parent = touchedActivity.getTaskFragment();
+ if (parent != null && parent.isEmbedded()) {
+ // Set the focused app directly if the focused window is currently embedded
+ final DisplayContent displayContent = touchedActivity.getDisplayContent();
+ displayContent.setFocusedApp(touchedActivity);
+ mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+ true /* updateInputWindows */);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b2e7b8f..31f943b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -771,10 +771,19 @@
return true;
}
- if (focusedApp.getTask() == activity.getTask()
- && focusedApp.getTaskFragment() != activity.getTaskFragment()) {
- // Do not use the activity window of another TaskFragment in the same leaf Task
- return false;
+ // If the candidate activity is currently being embedded in the focused task, the
+ // activity cannot be focused unless it is on the same TaskFragment as the focusedApp's.
+ TaskFragment parent = activity.getTaskFragment();
+ if (parent != null && parent.isEmbedded()) {
+ Task hostTask = focusedApp.getTask();
+ if (hostTask.isEmbedded()) {
+ // Use the hosting task if the current task is embedded.
+ hostTask = hostTask.getParent().asTaskFragment().getTask();
+ }
+ if (activity.isDescendantOf(hostTask)
+ && activity.getTaskFragment() != focusedApp.getTaskFragment()) {
+ return false;
+ }
}
}
@@ -4577,7 +4586,9 @@
return true;
}
- if (task.isOrganized()) {
+ // TODO(b/165794880): Freeform task organizer doesn't support drag-resize yet. Remove
+ // the special case when it does.
+ if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
return true;
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index eb5ab83..3bb72b2 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -306,7 +306,10 @@
boolean useSurfaceCrop = false;
final Task task = w.getTask();
if (task != null) {
- if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ // TODO(b/165794636): Remove the special case for freeform window once drag resizing is
+ // handled by WM shell.
+ if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN
+ && !task.inFreeformWindowingMode()) {
// If the window is in a TaskManaged by a TaskOrganizer then most cropping will
// be applied using the SurfaceControl hierarchy from the Organizer. This means
// we need to make sure that these changes in crop are reflected in the input
@@ -538,7 +541,8 @@
if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
if (recentsAnimationController.updateInputConsumerForApp(
mRecentsAnimationInputConsumer.mWindowHandle)) {
- mRecentsAnimationInputConsumer.show(mInputTransaction, w.mActivityRecord);
+ mRecentsAnimationInputConsumer.show(mInputTransaction,
+ recentsAnimationController.getHighestLayerTask());
mAddRecentsAnimationInputConsumerHandle = false;
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 895a82b..53af563 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -30,10 +30,6 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.StatusBarManager;
@@ -222,7 +218,7 @@
InsetsState getInsetsForWindow(WindowState target) {
final InsetsState originalState = mStateController.getInsetsForWindow(target);
final InsetsState state = adjustVisibilityForTransientTypes(originalState);
- return adjustVisibilityForIme(target, state, state == originalState);
+ return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
}
/**
@@ -252,38 +248,16 @@
return state;
}
- private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
+ // Navigation bar insets is always visible to IME.
+ private static InsetsState adjustVisibilityForIme(InsetsState originalState,
boolean copyState) {
- if (w.mIsImWindow) {
- // Navigation bar insets is always visible to IME.
- final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
- if (originalNavSource != null && !originalNavSource.isVisible()) {
- final InsetsState state = copyState ? new InsetsState(originalState)
- : originalState;
- final InsetsSource navSource = new InsetsSource(originalNavSource);
- navSource.setVisible(true);
- state.addSource(navSource);
- return state;
- }
- } else if (w.mActivityRecord != null && !w.mActivityRecord.mLastImeShown) {
- // During switching tasks with gestural navigation, if the IME is attached to
- // one app window on that time, even the next app window is behind the IME window,
- // conceptually the window should not receive the IME insets if the next window is
- // not eligible IME requester and ready to show IME on top of it.
- final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp();
- final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);
-
- if (originalImeSource != null && shouldImeAttachedToApp
- && (w.isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS)
- || !w.getRequestedVisibility(ITYPE_IME))) {
- final InsetsState state = copyState ? new InsetsState(originalState)
- : originalState;
-
- final InsetsSource imeSource = new InsetsSource(originalImeSource);
- imeSource.setVisible(false);
- state.addSource(imeSource);
- return state;
- }
+ final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
+ if (originalNavSource != null && !originalNavSource.isVisible()) {
+ final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
+ final InsetsSource navSource = new InsetsSource(originalNavSource);
+ navSource.setVisible(true);
+ state.addSource(navSource);
+ return state;
}
return originalState;
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 750de3b..d67d5fa 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -386,7 +386,9 @@
// can be committed before KEYGUARD_OCCLUDE transition is handled.
// Set mRequestForceTransition flag to make sure that the app transition animation
// is applied for such case.
- if (topActivity != null) {
+ // TODO(b/194243906): Fix this before enabling the remote keyguard animation.
+ if (WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation
+ && topActivity != null) {
topActivity.mRequestForceTransition = true;
}
updateKeyguardSleepToken(DEFAULT_DISPLAY);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 4f93c7a..c457df9 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -1102,6 +1102,23 @@
return mTargetActivityRecord.findMainWindow();
}
+ /**
+ * Returns the task with the highest layer, or null if none is found.
+ */
+ public Task getHighestLayerTask() {
+ int highestLayer = Integer.MIN_VALUE;
+ Task highestLayerTask = null;
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ TaskAnimationAdapter adapter = mPendingAnimations.get(i);
+ int layer = adapter.mTask.getPrefixOrderIndex();
+ if (layer > highestLayer) {
+ highestLayer = layer;
+ highestLayerTask = adapter.mTask;
+ }
+ }
+ return highestLayerTask;
+ }
+
boolean isAnimatingTask(Task task) {
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
if (task == mPendingAnimations.get(i).mTask) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 69ad59a..fec7ede 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3252,7 +3252,7 @@
boolean consumed = false;
if (traverseTopToBottom) {
for (int i = task.mChildren.size() - 1; i >= 0; --i) {
- final WindowContainer child = mChildren.get(i);
+ final WindowContainer child = task.mChildren.get(i);
if (child.asTaskFragment() != null) {
child.forAllLeafTaskFragments(callback, traverseTopToBottom);
} else if (child.asActivityRecord() != null && !consumed) {
@@ -3262,7 +3262,7 @@
}
} else {
for (int i = 0; i < task.mChildren.size(); i++) {
- final WindowContainer child = mChildren.get(i);
+ final WindowContainer child = task.mChildren.get(i);
if (child.asTaskFragment() != null) {
child.forAllLeafTaskFragments(callback, traverseTopToBottom);
} else if (child.asActivityRecord() != null && !consumed) {
@@ -4174,8 +4174,7 @@
}
private boolean canBeOrganized() {
- if (mForceNotOrganized || !mAtmService.mTaskOrganizerController
- .isSupportedWindowingMode(getWindowingMode())) {
+ if (mForceNotOrganized) {
return false;
}
// All root tasks can be organized
@@ -4332,7 +4331,7 @@
final int windowingMode = getWindowingMode();
final TaskOrganizerController controller = mWmService.mAtmService.mTaskOrganizerController;
- final ITaskOrganizer organizer = controller.getTaskOrganizer(windowingMode);
+ final ITaskOrganizer organizer = controller.getTaskOrganizer();
if (!forceUpdate && mTaskOrganizer == organizer) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 8a7688f..5d679cf 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1398,6 +1398,8 @@
} else {
prev.schedulePauseTimeout();
+ // Unset readiness since we now need to wait until this pause is complete.
+ mAtmService.getTransitionController().setReady(this, false /* ready */);
return true;
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 99f31ad..b17a939 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -16,9 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
@@ -67,14 +64,6 @@
class TaskOrganizerController extends ITaskOrganizerController.Stub {
private static final String TAG = "TaskOrganizerController";
- // The set of modes that are currently supports
- // TODO: Remove once the task organizer can support all modes
- @VisibleForTesting
- static final int[] UNSUPPORTED_WINDOWING_MODES = {
- WINDOWING_MODE_UNDEFINED,
- WINDOWING_MODE_FREEFORM
- };
-
private class DeathRecipient implements IBinder.DeathRecipient {
ITaskOrganizer mTaskOrganizer;
@@ -373,11 +362,6 @@
final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
mService.mRootWindowContainer.forAllTasks((task) -> {
- if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES,
- task.getWindowingMode())) {
- return;
- }
-
boolean returnTask = !task.mCreatedByOrganizer;
task.updateTaskOrganizerState(true /* forceUpdate */,
returnTask /* skipTaskAppeared */);
@@ -433,14 +417,8 @@
/**
* @return the task organizer key for a given windowing mode.
*/
- ITaskOrganizer getTaskOrganizer(int windowingMode) {
- return isSupportedWindowingMode(windowingMode)
- ? mTaskOrganizers.peekLast()
- : null;
- }
-
- boolean isSupportedWindowingMode(int winMode) {
- return !ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, winMode);
+ ITaskOrganizer getTaskOrganizer() {
+ return mTaskOrganizers.peekLast();
}
// Capture the animation surface control for activity's main window
@@ -993,9 +971,6 @@
for (int k = 0; k < tasks.size(); k++) {
final Task task = tasks.get(k);
final int mode = task.getWindowingMode();
- if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, mode)) {
- continue;
- }
pw.println(innerPrefix + " ("
+ WindowConfiguration.windowingModeToString(mode) + ") " + task);
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 6bfa611..da16de7 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -20,6 +20,8 @@
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
@@ -36,6 +38,7 @@
import static android.view.WindowManager.TransitionFlags;
import static android.view.WindowManager.TransitionType;
import static android.view.WindowManager.transitTypeToString;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -657,7 +660,7 @@
ArrayMap<WindowContainer, Integer> reasons = new ArrayMap<>();
for (int i = mParticipants.size() - 1; i >= 0; --i) {
ActivityRecord r = mParticipants.valueAt(i).asActivityRecord();
- if (r == null) continue;
+ if (r == null || !r.mVisibleRequested) continue;
// At this point, r is "ready", but if it's not "ALL ready" then it is probably only
// ready due to starting-window.
reasons.put(r, (r.mStartingData instanceof SplashScreenStartingData
@@ -1066,6 +1069,7 @@
final ActivityManager.RunningTaskInfo tinfo = new ActivityManager.RunningTaskInfo();
task.fillTaskInfo(tinfo);
change.setTaskInfo(tinfo);
+ change.setRotationAnimation(getTaskRotationAnimation(task));
}
out.addChange(change);
}
@@ -1073,6 +1077,23 @@
return out;
}
+ private static int getTaskRotationAnimation(@NonNull Task task) {
+ final ActivityRecord top = task.getTopVisibleActivity();
+ if (top == null) return ROTATION_ANIMATION_UNSPECIFIED;
+ final WindowState mainWin = top.findMainWindow(false);
+ if (mainWin == null) return ROTATION_ANIMATION_UNSPECIFIED;
+ int anim = mainWin.getRotationAnimationHint();
+ if (anim >= 0) return anim;
+ anim = mainWin.getAttrs().rotationAnimation;
+ if (anim != ROTATION_ANIMATION_SEAMLESS) return anim;
+ if (mainWin != task.mDisplayContent.getDisplayPolicy().getTopFullscreenOpaqueWindow()
+ || !top.matchParentBounds()) {
+ // At the moment, we only support seamless rotation if there is only one window showing.
+ return ROTATION_ANIMATION_UNSPECIFIED;
+ }
+ return mainWin.getAttrs().rotationAnimation;
+ }
+
boolean getLegacyIsReady() {
return mState == STATE_STARTED && mSyncId >= 0 && mSyncEngine.isReady(mSyncId);
}
@@ -1166,6 +1187,9 @@
final DisplayContent dc = wc.asDisplayContent();
if (dc != null) {
flags |= FLAG_IS_DISPLAY;
+ if (dc.hasAlertWindowSurfaces()) {
+ flags |= FLAG_DISPLAY_HAS_ALERT_WINDOWS;
+ }
}
if (isWallpaper(wc)) {
flags |= FLAG_IS_WALLPAPER;
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index ab4f1f6..8c93377 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -157,12 +157,12 @@
"android.hardware.input.classifier@1.0",
"android.hardware.ir@1.0",
"android.hardware.light@2.0",
- "android.hardware.memtrack-V1-ndk_platform",
+ "android.hardware.memtrack-V1-ndk",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
"android.hardware.power-V2-cpp",
"android.hardware.power.stats@1.0",
- "android.hardware.power.stats-V1-ndk_platform",
+ "android.hardware.power.stats-V1-ndk",
"android.hardware.thermal@1.0",
"android.hardware.tv.input@1.0",
"android.hardware.vibrator-V2-cpp",
@@ -175,7 +175,7 @@
"android.frameworks.schedulerservice@1.0",
"android.frameworks.sensorservice@1.0",
"android.frameworks.stats@1.0",
- "android.frameworks.stats-V1-ndk_platform",
+ "android.frameworks.stats-V1-ndk",
"android.system.suspend.control-V1-cpp",
"android.system.suspend.control.internal-cpp",
"android.system.suspend@1.0",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index be8b21c..f641d21 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -648,7 +648,6 @@
private final DevicePolicyCacheImpl mPolicyCache = new DevicePolicyCacheImpl();
private final DeviceStateCacheImpl mStateCache = new DeviceStateCacheImpl();
- private EnterpriseSpecificIdCalculator mEsidCalculator;
/**
* Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p
@@ -1474,10 +1473,6 @@
return new LockPatternUtils(mContext);
}
- EnterpriseSpecificIdCalculator newEnterpriseSpecificIdCalculator() {
- return new EnterpriseSpecificIdCalculator(mContext);
- }
-
boolean storageManagerIsFileBasedEncryptionEnabled() {
return StorageManager.isFileEncryptedNativeOnly();
}
@@ -3126,10 +3121,6 @@
factoryResetIfDelayedEarlier();
ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this.
-
- // This is constructed here as EnterpriseSpecificIdCalculator depends on telephony
- // and wifi service and these services are only fully available at this stage.
- mEsidCalculator = mInjector.newEnterpriseSpecificIdCalculator();
break;
}
}
@@ -16927,8 +16918,6 @@
@Override
public void setOrganizationIdForUser(
@NonNull String callerPackage, @NonNull String organizationId, int userId) {
- Preconditions.checkState(mEsidCalculator != null,
- "setOrganizationIdForUser can't be called before boot phase completion");
if (!mHasFeature) {
return;
}
@@ -16962,7 +16951,10 @@
+ "be changed");
final String dpcPackage = owner.info.getPackageName();
mInjector.binderWithCleanCallingIdentity(() -> {
- final String esid = mEsidCalculator.calculateEnterpriseId(dpcPackage,
+ EnterpriseSpecificIdCalculator esidCalculator =
+ new EnterpriseSpecificIdCalculator(mContext);
+
+ final String esid = esidCalculator.calculateEnterpriseId(dpcPackage,
organizationId);
owner.mOrganizationId = organizationId;
owner.mEnrollmentSpecificId = esid;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
index 29091ce..df7f308 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
@@ -51,19 +51,13 @@
EnterpriseSpecificIdCalculator(Context context) {
TelephonyManager telephonyService = context.getSystemService(TelephonyManager.class);
- if (telephonyService != null) {
- mImei = telephonyService.getImei(0);
- mMeid = telephonyService.getMeid(0);
- } else {
- mImei = "";
- mMeid = "";
- }
+ Preconditions.checkState(telephonyService != null, "Unable to access telephony service");
+ mImei = telephonyService.getImei(0);
+ mMeid = telephonyService.getMeid(0);
mSerialNumber = Build.getSerial();
WifiManager wifiManager = context.getSystemService(WifiManager.class);
- String[] macAddresses = null;
- if (wifiManager != null) {
- macAddresses = wifiManager.getFactoryMacAddresses();
- }
+ Preconditions.checkState(wifiManager != null, "Unable to access WiFi service");
+ final String[] macAddresses = wifiManager.getFactoryMacAddresses();
if (macAddresses == null || macAddresses.length == 0) {
mMacAddress = "";
} else {
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index 988c02b..1bcc3d1 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -32,6 +32,7 @@
"androidx.test.runner",
"junit",
"kotlin-test",
+ "kotlin-reflect",
"services.core",
"servicestests-utils",
"truth-prebuilt",
diff --git a/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING b/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING
new file mode 100644
index 0000000..cacfcf0
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "PackageManagerServiceUnitTests"
+ }
+ ]
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
new file mode 100644
index 0000000..a7644ec
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.Intent
+import android.content.pm.ApplicationInfo
+import android.content.pm.ConfigurationInfo
+import android.content.pm.FeatureGroupInfo
+import android.content.pm.FeatureInfo
+import android.content.pm.PackageManager
+import android.content.pm.SigningDetails
+import android.content.pm.parsing.ParsingPackage
+import android.content.pm.parsing.component.ParsedActivity
+import android.content.pm.parsing.component.ParsedAttribution
+import android.content.pm.parsing.component.ParsedComponent
+import android.content.pm.parsing.component.ParsedInstrumentation
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.content.pm.parsing.component.ParsedPermission
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import android.content.pm.parsing.component.ParsedProcess
+import android.content.pm.parsing.component.ParsedProvider
+import android.content.pm.parsing.component.ParsedService
+import android.content.pm.parsing.component.ParsedUsesPermission
+import android.net.Uri
+import android.os.Bundle
+import android.os.Parcelable
+import android.util.ArraySet
+import android.util.SparseArray
+import android.util.SparseIntArray
+import com.android.internal.R
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.PackageImpl
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.whenever
+import java.security.KeyPairGenerator
+import java.security.PublicKey
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, PackageImpl::class) {
+
+ override val defaultImpl = PackageImpl.forTesting("com.example.test")
+ override val creator = PackageImpl.CREATOR
+
+ override val excludedMethods = listOf(
+ // Internal methods
+ "toAppInfoToString",
+ "toAppInfoWithoutState",
+ "toAppInfoWithoutStateWithoutFlags",
+ "assignDerivedFields",
+ "buildFakeForDeletion",
+ "capPermissionPriorities",
+ "forParsing",
+ "forTesting",
+ "getBaseAppDataCredentialProtectedDirForSystemUser",
+ "getBaseAppDataDeviceProtectedDirForSystemUser",
+ "getBoolean",
+ "setBoolean",
+ "hideAsFinal",
+ "hideAsParsed",
+ "markNotActivitiesAsNotExportedIfSingleUser",
+ "sortActivities",
+ "sortReceivers",
+ "sortServices",
+ "setAllComponentsDirectBootAware",
+ // Tested through setting minor/major manually
+ "setLongVersionCode",
+ "getLongVersionCode",
+ // Tested through constructor
+ "getManifestPackageName",
+ "setManifestPackageName",
+ // Utility methods
+ "getStorageUuid",
+ // Removal not tested, irrelevant for parcelling concerns
+ "removeUsesOptionalLibrary",
+ "clearAdoptPermissions",
+ "clearOriginalPackages",
+ "clearProtectedBroadcasts",
+ "removePermission",
+ "removeUsesLibrary",
+ "removeUsesOptionalNativeLibrary",
+ // Tested manually
+ "getMimeGroups",
+ "getRequestedPermissions",
+ // Tested through asSplit
+ "asSplit",
+ "getSplitNames",
+ "getSplitCodePaths",
+ "getSplitRevisionCodes",
+ "getSplitFlags",
+ "getSplitClassLoaderNames",
+ "getSplitDependencies",
+ "setSplitCodePaths",
+ "setSplitClassLoaderName",
+ "setSplitHasCode",
+ )
+
+ override val baseParams = listOf(
+ AndroidPackage::getAppComponentFactory,
+ AndroidPackage::getAutoRevokePermissions,
+ AndroidPackage::getBackupAgentName,
+ AndroidPackage::getBanner,
+ AndroidPackage::getBaseApkPath,
+ AndroidPackage::getBaseRevisionCode,
+ AndroidPackage::getCategory,
+ AndroidPackage::getClassLoaderName,
+ AndroidPackage::getClassName,
+ AndroidPackage::getCompatibleWidthLimitDp,
+ AndroidPackage::getCompileSdkVersion,
+ AndroidPackage::getCompileSdkVersionCodeName,
+ AndroidPackage::getDataExtractionRules,
+ AndroidPackage::getDescriptionRes,
+ AndroidPackage::getFullBackupContent,
+ AndroidPackage::getGwpAsanMode,
+ AndroidPackage::getIconRes,
+ AndroidPackage::getInstallLocation,
+ AndroidPackage::getLabelRes,
+ AndroidPackage::getLargestWidthLimitDp,
+ AndroidPackage::getLogo,
+ AndroidPackage::getManageSpaceActivityName,
+ AndroidPackage::getMemtagMode,
+ AndroidPackage::getMinSdkVersion,
+ AndroidPackage::getNativeHeapZeroInitialized,
+ AndroidPackage::getNativeLibraryDir,
+ AndroidPackage::getNativeLibraryRootDir,
+ AndroidPackage::getNetworkSecurityConfigRes,
+ AndroidPackage::getNonLocalizedLabel,
+ AndroidPackage::getOverlayCategory,
+ AndroidPackage::getOverlayPriority,
+ AndroidPackage::getOverlayTarget,
+ AndroidPackage::getOverlayTargetName,
+ AndroidPackage::getPackageName,
+ AndroidPackage::getPath,
+ AndroidPackage::getPermission,
+ AndroidPackage::getPrimaryCpuAbi,
+ AndroidPackage::getProcessName,
+ AndroidPackage::getRealPackage,
+ AndroidPackage::getRequiredAccountType,
+ AndroidPackage::getRequiresSmallestWidthDp,
+ AndroidPackage::getResizeableActivity,
+ AndroidPackage::getRestrictedAccountType,
+ AndroidPackage::getRoundIconRes,
+ AndroidPackage::getSeInfo,
+ AndroidPackage::getSeInfoUser,
+ AndroidPackage::getSecondaryCpuAbi,
+ AndroidPackage::getSecondaryNativeLibraryDir,
+ AndroidPackage::getSharedUserId,
+ AndroidPackage::getSharedUserLabel,
+ AndroidPackage::getStaticSharedLibName,
+ AndroidPackage::getStaticSharedLibVersion,
+ AndroidPackage::getTargetSandboxVersion,
+ AndroidPackage::getTargetSdkVersion,
+ AndroidPackage::getTaskAffinity,
+ AndroidPackage::getTheme,
+ AndroidPackage::getUiOptions,
+ AndroidPackage::getUid,
+ AndroidPackage::getVersionName,
+ AndroidPackage::getZygotePreloadName,
+ AndroidPackage::isAllowAudioPlaybackCapture,
+ AndroidPackage::isAllowBackup,
+ AndroidPackage::isAllowClearUserData,
+ AndroidPackage::isAllowClearUserDataOnFailedRestore,
+ AndroidPackage::isAllowNativeHeapPointerTagging,
+ AndroidPackage::isAllowTaskReparenting,
+ AndroidPackage::isBackupInForeground,
+ AndroidPackage::isBaseHardwareAccelerated,
+ AndroidPackage::isCantSaveState,
+ AndroidPackage::isCoreApp,
+ AndroidPackage::isCrossProfile,
+ AndroidPackage::isDebuggable,
+ AndroidPackage::isDefaultToDeviceProtectedStorage,
+ AndroidPackage::isDirectBootAware,
+ AndroidPackage::isEnabled,
+ AndroidPackage::isExternalStorage,
+ AndroidPackage::isExtractNativeLibs,
+ AndroidPackage::isFactoryTest,
+ AndroidPackage::isForceQueryable,
+ AndroidPackage::isFullBackupOnly,
+ AndroidPackage::isGame,
+ AndroidPackage::isHasCode,
+ AndroidPackage::isHasDomainUrls,
+ AndroidPackage::isHasFragileUserData,
+ AndroidPackage::isIsolatedSplitLoading,
+ AndroidPackage::isKillAfterRestore,
+ AndroidPackage::isLargeHeap,
+ AndroidPackage::isMultiArch,
+ AndroidPackage::isNativeLibraryRootRequiresIsa,
+ AndroidPackage::isOdm,
+ AndroidPackage::isOem,
+ AndroidPackage::isOverlay,
+ AndroidPackage::isOverlayIsStatic,
+ AndroidPackage::isPartiallyDirectBootAware,
+ AndroidPackage::isPersistent,
+ AndroidPackage::isPrivileged,
+ AndroidPackage::isProduct,
+ AndroidPackage::isProfileableByShell,
+ AndroidPackage::isRequestLegacyExternalStorage,
+ AndroidPackage::isRequiredForAllUsers,
+ AndroidPackage::isResizeableActivityViaSdkVersion,
+ AndroidPackage::isRestoreAnyVersion,
+ AndroidPackage::isSignedWithPlatformKey,
+ AndroidPackage::isStaticSharedLibrary,
+ AndroidPackage::isStub,
+ AndroidPackage::isSupportsRtl,
+ AndroidPackage::isSystem,
+ AndroidPackage::isSystemExt,
+ AndroidPackage::isTestOnly,
+ AndroidPackage::isUse32BitAbi,
+ AndroidPackage::isUseEmbeddedDex,
+ AndroidPackage::isUsesCleartextTraffic,
+ AndroidPackage::isUsesNonSdkApi,
+ AndroidPackage::isVendor,
+ AndroidPackage::isVisibleToInstantApps,
+ AndroidPackage::isVmSafeMode,
+ AndroidPackage::getMaxAspectRatio,
+ AndroidPackage::getMinAspectRatio,
+ AndroidPackage::hasPreserveLegacyExternalStorage,
+ AndroidPackage::hasRequestForegroundServiceExemption,
+ AndroidPackage::hasRequestRawExternalStorageAccess,
+ )
+
+ override fun extraParams() = listOf(
+ getter(AndroidPackage::getVolumeUuid, "57554103-df3e-4475-ae7a-8feba49353ac"),
+ getter(AndroidPackage::isProfileable, true),
+ getter(AndroidPackage::getVersionCode, 3),
+ getter(AndroidPackage::getVersionCodeMajor, 9),
+ getter(AndroidPackage::getUpgradeKeySets, setOf("testUpgradeKeySet")),
+ getter(AndroidPackage::isAnyDensity, false, 0),
+ getter(AndroidPackage::isResizeable, false, 0),
+ getter(AndroidPackage::isSupportsSmallScreens, false, 0),
+ getter(AndroidPackage::isSupportsNormalScreens, false, 0),
+ getter(AndroidPackage::isSupportsLargeScreens, false, 0),
+ getter(AndroidPackage::isSupportsExtraLargeScreens, false, 0),
+ adder(AndroidPackage::getAdoptPermissions, "test.adopt.PERMISSION"),
+ adder(AndroidPackage::getOriginalPackages, "com.test.original"),
+ adder(AndroidPackage::getImplicitPermissions, "test.implicit.PERMISSION"),
+ adder(AndroidPackage::getLibraryNames, "testLibraryName"),
+ adder(AndroidPackage::getProtectedBroadcasts, "test.protected.BROADCAST"),
+ adder(AndroidPackage::getQueriesPackages, "com.test.package.queries"),
+ adder(AndroidPackage::getQueriesProviders, "com.test.package.queries.provider"),
+ adder(AndroidPackage::getUsesLibraries, "testUsesLibrary"),
+ adder(AndroidPackage::getUsesNativeLibraries, "testUsesNativeLibrary"),
+ adder(AndroidPackage::getUsesOptionalLibraries, "testUsesOptionalLibrary"),
+ adder(AndroidPackage::getUsesOptionalNativeLibraries, "testUsesOptionalNativeLibrary"),
+ adder(AndroidPackage::getUsesStaticLibraries, "testUsesStaticLibrary"),
+ getSetByValue(
+ AndroidPackage::getUsesStaticLibrariesVersions,
+ PackageImpl::addUsesStaticLibraryVersion,
+ (testCounter++).toLong(),
+ transformGet = { it?.singleOrNull() }
+ ),
+ getSetByValue(
+ AndroidPackage::areAttributionsUserVisible,
+ ParsingPackage::setAttributionsAreUserVisible,
+ true
+ ),
+ getSetByValue2(
+ AndroidPackage::getOverlayables,
+ PackageImpl::addOverlayable,
+ "testOverlayableName" to "testActorName",
+ transformGet = { "testOverlayableName" to it["testOverlayableName"] }
+ ),
+ getSetByValue(
+ AndroidPackage::getMetaData,
+ PackageImpl::setMetaData,
+ "testBundleKey" to "testBundleValue",
+ transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
+ transformSet = { Bundle().apply { putString(it.first, it.second) } }
+ ),
+ getSetByValue(
+ AndroidPackage::getAttributions,
+ PackageImpl::addAttribution,
+ Triple("testTag", 13, listOf("testInherit")),
+ transformGet = { it.singleOrNull()?.let { Triple(it.tag, it.label, it.inheritFrom) } },
+ transformSet = { it?.let { ParsedAttribution(it.first, it.second, it.third) } }
+ ),
+ getSetByValue2(
+ AndroidPackage::getKeySetMapping,
+ PackageImpl::addKeySet,
+ "testKeySetName" to testKey(),
+ transformGet = { "testKeySetName" to it["testKeySetName"]?.singleOrNull() },
+ ),
+ getSetByValue(
+ AndroidPackage::getPermissionGroups,
+ PackageImpl::addPermissionGroup,
+ "test.permission.GROUP",
+ transformGet = { it.singleOrNull()?.name },
+ transformSet = { ParsedPermissionGroup().apply { setName(it) } }
+ ),
+ getSetByValue2(
+ AndroidPackage::getPreferredActivityFilters,
+ PackageImpl::addPreferredActivityFilter,
+ "TestClassName" to ParsedIntentInfo().apply {
+ addDataScheme("http")
+ addDataAuthority("test.pm.server.android.com", null)
+ },
+ transformGet = { it.singleOrNull()?.let { it.first to it.second } },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ { it.first },
+ { it.second.schemesIterator().asSequence().singleOrNull() },
+ { it.second.authoritiesIterator().asSequence().singleOrNull()?.host },
+ )
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getQueriesIntents,
+ PackageImpl::addQueriesIntent,
+ Intent(Intent.ACTION_VIEW, Uri.parse("https://test.pm.server.android.com")),
+ transformGet = { it.singleOrNull() },
+ compare = { first, second -> first?.filterEquals(second) },
+ ),
+ getSetByValue(
+ AndroidPackage::getRestrictUpdateHash,
+ PackageImpl::setRestrictUpdateHash,
+ byteArrayOf(0, 1, 2, 3, 4),
+ compare = ByteArray::contentEquals
+ ),
+ getSetByValue(
+ AndroidPackage::getSigningDetails,
+ PackageImpl::setSigningDetails,
+ testKey(),
+ transformGet = { it.publicKeys?.takeIf { it.size > 0 }?.valueAt(0) },
+ transformSet = {
+ SigningDetails(
+ null,
+ SigningDetails.SignatureSchemeVersion.UNKNOWN,
+ ArraySet<PublicKey>().apply { add(it) },
+ null
+ )
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getUsesStaticLibrariesCertDigests,
+ PackageImpl::addUsesStaticLibraryCertDigests,
+ arrayOf("testCertDigest"),
+ transformGet = { it?.singleOrNull() },
+ compare = Array<String?>?::contentEquals
+ ),
+ getSetByValue(
+ AndroidPackage::getActivities,
+ PackageImpl::addActivity,
+ "TestActivityName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
+ ),
+ getSetByValue(
+ AndroidPackage::getReceivers,
+ PackageImpl::addReceiver,
+ "TestReceiverName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
+ ),
+ getSetByValue(
+ AndroidPackage::getServices,
+ PackageImpl::addService,
+ "TestServiceName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedService().apply { name = it }.withMimeGroups() }
+ ),
+ getSetByValue(
+ AndroidPackage::getProviders,
+ PackageImpl::addProvider,
+ "TestProviderName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedProvider().apply { name = it }.withMimeGroups() }
+ ),
+ getSetByValue(
+ AndroidPackage::getInstrumentations,
+ PackageImpl::addInstrumentation,
+ "TestInstrumentationName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedInstrumentation().apply { name = it } }
+ ),
+ getSetByValue(
+ AndroidPackage::getConfigPreferences,
+ PackageImpl::addConfigPreference,
+ testCounter++,
+ transformGet = { it.singleOrNull()?.reqGlEsVersion ?: -1 },
+ transformSet = { ConfigurationInfo().apply { reqGlEsVersion = it } }
+ ),
+ getSetByValue(
+ AndroidPackage::getFeatureGroups,
+ PackageImpl::addFeatureGroup,
+ "test.feature.GROUP",
+ transformGet = { it.singleOrNull()?.features?.singleOrNull()?.name.orEmpty() },
+ transformSet = {
+ FeatureGroupInfo().apply {
+ features = arrayOf(FeatureInfo().apply { name = it })
+ }
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getPermissions,
+ PackageImpl::addPermission,
+ "test.PERMISSION",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedPermission().apply { name = it } }
+ ),
+ getSetByValue(
+ AndroidPackage::getUsesPermissions,
+ PackageImpl::addUsesPermission,
+ "test.USES_PERMISSION",
+ transformGet = {
+ // Need to strip implicit permission, which calls addUsesPermission when added
+ it.filterNot { it.name == "test.implicit.PERMISSION" }
+ .singleOrNull()?.name.orEmpty()
+ },
+ transformSet = { ParsedUsesPermission(it, 0) }
+ ),
+ getSetByValue(
+ AndroidPackage::getReqFeatures,
+ PackageImpl::addReqFeature,
+ "test.feature.INFO",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { FeatureInfo().apply { name = it } }
+ ),
+ getSetByValue(
+ AndroidPackage::getMinExtensionVersions,
+ PackageImpl::setMinExtensionVersions,
+ SparseIntArray().apply { put(testCounter++, testCounter++) },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ { it.size() },
+ { it.keyAt(0) },
+ { it.valueAt(0) },
+ )
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getProcesses,
+ PackageImpl::setProcesses,
+ mapOf("testProcess" to ParsedProcess().apply { name = "testProcessName" }),
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ { it["testProcess"]?.name },
+ )
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getProperties,
+ PackageImpl::addProperty,
+ PackageManager.Property(
+ "testPropertyName",
+ "testPropertyValue",
+ "testPropertyClassName",
+ "testPropertyPackageName"
+ ),
+ transformGet = { it["testPropertyName"] },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ PackageManager.Property::getName,
+ PackageManager.Property::getClassName,
+ PackageManager.Property::getPackageName,
+ PackageManager.Property::getString,
+ )
+ }
+ ),
+ )
+
+ override fun initialObject() = PackageImpl.forParsing(
+ "com.example.test",
+ "/test/test/base.apk",
+ "/test/test",
+ mockThrowOnUnmocked {
+ whenever(getInteger(R.styleable.AndroidManifest_revisionCode, 0)) { 4 }
+ whenever(getBoolean(R.styleable.AndroidManifest_isolatedSplits, false)) { true }
+
+ // Return invalid values here so that the getter/setter is tested properly
+ whenever(getInteger(R.styleable.AndroidManifest_versionCode, 0)) { -1 }
+ whenever(getInteger(R.styleable.AndroidManifest_versionCodeMajor, 0)) { -1 }
+ whenever(
+ getNonConfigurationString(
+ R.styleable.AndroidManifest_versionName,
+ 0
+ )
+ ) { "" }
+ whenever(getInteger(R.styleable.AndroidManifest_compileSdkVersion, 0)) { 31 }
+ whenever(
+ getNonConfigurationString(
+ R.styleable.AndroidManifest_compileSdkVersionCodename,
+ 0
+ )
+ ) { "" }
+ },
+ true
+ )
+ .asSplit(
+ arrayOf("testSplitNameZero", "testSplitNameOne"),
+ arrayOf("/test/testSplitZero.apk", "/test/testSplitOne.apk"),
+ intArrayOf(10, 11),
+ SparseArray<IntArray>().apply {
+ put(0, intArrayOf(-1))
+ put(1, intArrayOf(0))
+ }
+ )
+ .setSplitHasCode(0, true)
+ .setSplitHasCode(1, false)
+ .setSplitClassLoaderName(0, "testSplitClassLoaderNameZero")
+ .setSplitClassLoaderName(1, "testSplitClassLoaderNameOne")
+
+ override fun extraAssertions(before: Parcelable, after: Parcelable) {
+ super.extraAssertions(before, after)
+ after as PackageImpl
+ expect.that(after.manifestPackageName).isEqualTo("com.example.test")
+ expect.that(after.isCoreApp).isTrue()
+ expect.that(after.isIsolatedSplitLoading).isEqualTo(true)
+ expect.that(after.longVersionCode).isEqualTo(38654705667)
+ expect.that(after.requestedPermissions)
+ .containsExactlyElementsIn(after.usesPermissions.map { it.name })
+ .inOrder()
+
+ expect.that(after.mimeGroups).containsExactly(
+ "TestActivityName/mimeGroup",
+ "TestReceiverName/mimeGroup",
+ "TestServiceName/mimeGroup",
+ "TestProviderName/mimeGroup"
+ )
+
+ expect.that(after.splitNames).asList()
+ .containsExactly("testSplitNameZero", "testSplitNameOne")
+ .inOrder()
+ expect.that(after.splitCodePaths).asList()
+ .containsExactly("/test/testSplitZero.apk", "/test/testSplitOne.apk")
+ .inOrder()
+ expect.that(after.splitRevisionCodes).asList()
+ .containsExactly(10, 11)
+ .inOrder()
+ expect.that(after.splitFlags).asList()
+ .containsExactly(ApplicationInfo.FLAG_HAS_CODE, 0)
+ .inOrder()
+ expect.that(after.splitClassLoaderNames).asList()
+ .containsExactly("testSplitClassLoaderNameZero", "testSplitClassLoaderNameOne")
+ .inOrder()
+
+ expect.that(after.splitDependencies).isNotNull()
+ after.splitDependencies?.let {
+ expect.that(it.size()).isEqualTo(2)
+ expect.that(it.get(0)).asList().containsExactly(-1)
+ expect.that(it.get(1)).asList().containsExactly(0)
+ }
+ }
+
+ private fun testKey() = KeyPairGenerator.getInstance("RSA")
+ .generateKeyPair()
+ .public
+
+ private fun <T : ParsedComponent> T.withMimeGroups() = apply {
+ val componentName = name
+ addIntent(ParsedIntentInfo().apply {
+ addMimeGroup("$componentName/mimeGroup")
+ })
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt
new file mode 100644
index 0000000..e16a187
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.util.IgnoreableExpect
+import com.google.common.truth.Expect
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import java.util.Objects
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction
+import kotlin.reflect.KFunction1
+import kotlin.reflect.KFunction2
+import kotlin.reflect.KFunction3
+import kotlin.reflect.KVisibility
+import kotlin.reflect.full.allSuperclasses
+import kotlin.reflect.full.createInstance
+import kotlin.reflect.full.isSubclassOf
+import kotlin.reflect.full.memberFunctions
+import kotlin.reflect.full.memberProperties
+import kotlin.reflect.full.staticProperties
+import kotlin.reflect.jvm.jvmErasure
+
+
+@ExperimentalContracts
+abstract class ParcelableComponentTest(
+ private val getterType: KClass<*>,
+ private val setterType: KClass<out Parcelable>
+) {
+
+ companion object {
+ private val DEFAULT_EXCLUDED = listOf(
+ // Java
+ "toString",
+ "equals",
+ "hashCode",
+ // Parcelable
+ "getStability",
+ "describeContents",
+ "writeToParcel",
+ // @DataClass
+ "__metadata"
+ )
+ }
+
+ internal val ignoreableExpect = IgnoreableExpect()
+
+ // Hides internal type
+ @get:Rule
+ val ignoreableAsTestRule: TestRule = ignoreableExpect
+
+ val expect: Expect
+ get() = ignoreableExpect.expect
+
+ protected var testCounter = 1
+
+ protected abstract val defaultImpl: Any
+ protected abstract val creator: Parcelable.Creator<out Parcelable>
+
+ protected open val excludedMethods: Collection<String> = emptyList()
+
+ protected abstract val baseParams: Collection<KFunction1<*, Any?>>
+
+ private val getters = getterType.memberFunctions
+ .filterNot { DEFAULT_EXCLUDED.contains(it.name) }
+
+ private val setters = setterType.memberFunctions
+ .filterNot { DEFAULT_EXCLUDED.contains(it.name) }
+
+ constructor(kClass: KClass<out Parcelable>) : this(kClass, kClass)
+
+ @Before
+ fun checkNoPublicFields() {
+ // Fields are not currently testable, and the idea is to enforce interface access for
+ // immutability purposes, so disallow any public fields from existing.
+ expect.that(getterType.memberProperties.filter { it.visibility == KVisibility.PUBLIC }
+ .filterNot { DEFAULT_EXCLUDED.contains(it.name) })
+ .isEmpty()
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <ObjectType, ReturnType> buildParams(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ ): Param? {
+ return buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(
+ getFunction,
+ autoValue(getFunction) as ReturnType ?: return null
+ )
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> buildParams(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ value: SetType,
+ ): Param? {
+ return getSetByValue<ObjectType, ReturnType, SetType, Any?>(
+ getFunction,
+ findSetFunction(getFunction) ?: return null,
+ value
+ )
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <ObjectType, ReturnType> findSetFunction(
+ getFunction: KFunction1<ObjectType, ReturnType>
+ ): KFunction2<ObjectType, ReturnType, Any?>? {
+ val getFunctionName = getFunction.name
+ val prefix = when {
+ getFunctionName.startsWith("get") -> "get"
+ getFunctionName.startsWith("is") -> "is"
+ getFunctionName.startsWith("has") -> "has"
+ else -> throw IllegalArgumentException("Unsupported method name $getFunctionName")
+ }
+ val setFunctionName = "set" + getFunctionName.removePrefix(prefix)
+ val setFunction = setters.filter { it.name == setFunctionName }
+ .minByOrNull { it.parameters.size }
+
+ if (setFunction == null) {
+ expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
+ .fail()
+ return null
+ }
+
+ return setFunction as KFunction2<ObjectType, ReturnType, Any?>
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <ObjectType, ReturnType, SetType> findAddFunction(
+ getFunction: KFunction1<ObjectType, ReturnType>
+ ): KFunction2<ObjectType, SetType, Any?>? {
+ val getFunctionName = getFunction.name
+ if (!getFunctionName.startsWith("get")) {
+ throw IllegalArgumentException("Unsupported method name $getFunctionName")
+ }
+
+ val setFunctionName = "add" + getFunctionName.removePrefix("get").run {
+ // Remove plurality
+ when {
+ endsWith("ies") -> "${removeSuffix("ies")}y"
+ endsWith("s") -> removeSuffix("s")
+ else -> this
+ }
+ }
+
+ val setFunction = setters.filter { it.name == setFunctionName }
+ .minByOrNull { it.parameters.size }
+
+ if (setFunction == null) {
+ expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
+ .fail()
+ return null
+ }
+
+ return setFunction as KFunction2<ObjectType, SetType, Any?>
+ }
+
+ protected fun <ObjectType, ReturnType> getter(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ valueToSet: ReturnType
+ ) = buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(getFunction, valueToSet)
+
+ protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getter(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ expectedValue: CompareType,
+ valueToSet: SetType
+ ): Param? {
+ return getSetByValue(
+ getFunction,
+ findSetFunction(getFunction) ?: return null,
+ value = expectedValue,
+ transformSet = { valueToSet }
+ )
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ protected fun <ObjectType, ReturnType> adder(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ value: ReturnType,
+ ): Param? {
+ return getSetByValue(
+ getFunction,
+ findAddFunction<ObjectType, Any?, ReturnType>(getFunction) ?: return null,
+ value,
+ transformGet = {
+ // Primitive arrays don't implement Iterable, so cast manually
+ when (it) {
+ is BooleanArray -> it.singleOrNull()
+ is IntArray -> it.singleOrNull()
+ is LongArray -> it.singleOrNull()
+ is Iterable<*> -> it.singleOrNull()
+ else -> null
+ }
+ },
+ )
+ }
+
+ /**
+ * Method to provide custom getter and setter logic for values which are not simple primitives
+ * or cannot be directly compared using [Objects.equals].
+ *
+ * @param getFunction the getter function which will be called and marked as tested
+ * @param setFunction the setter function which will be called and marked as tested
+ * @param value the value for comparison through the parcel-unparcel cycle, which can be
+ * anything, like the [String] ID of an inner object
+ * @param transformGet the function to transform the result of [getFunction] into [value]
+ * @param transformSet the function to transform [value] into an input for [setFunction]
+ * @param compare the function that compares the pre/post-parcel [value] objects
+ */
+ @Suppress("UNCHECKED_CAST")
+ protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getSetByValue(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ setFunction: KFunction2<ObjectType, SetType, Any?>,
+ value: CompareType,
+ transformGet: (ReturnType) -> CompareType = { it as CompareType },
+ transformSet: (CompareType) -> SetType = { it as SetType },
+ compare: (CompareType, CompareType) -> Boolean? = Objects::equals
+ ) = Param(
+ getFunction.name,
+ { transformGet(getFunction.call(it as ObjectType)) },
+ setFunction.name,
+ { setFunction.call(it.first() as ObjectType, transformSet(it[1] as CompareType)) },
+ { value },
+ { first, second -> compare(first as CompareType, second as CompareType) == true }
+ )
+
+ /**
+ * Variant of [getSetByValue] that allows specifying a [setFunction] with 2 inputs.
+ */
+ @Suppress("UNCHECKED_CAST")
+ protected fun <ObjectType, ReturnType, SetType1 : Any?, SetType2 : Any?, CompareType : Any?>
+ getSetByValue2(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ setFunction: KFunction3<ObjectType, SetType1, SetType2, Any>,
+ value: CompareType,
+ transformGet: (ReturnType) -> CompareType = { it as CompareType },
+ transformSet: (CompareType) -> Pair<SetType1, SetType2> =
+ { it as Pair<SetType1, SetType2> },
+ compare: (CompareType, CompareType) -> Boolean = Objects::equals
+ ) = Param(
+ getFunction.name,
+ { transformGet(getFunction.call(it as ObjectType)) },
+ setFunction.name,
+ {
+ val pair = transformSet(it[1] as CompareType)
+ setFunction.call(it.first() as ObjectType, pair.first, pair.second)
+ },
+ { value },
+ { first, second -> compare(first as CompareType, second as CompareType) }
+ )
+
+ protected fun autoValue(getFunction: KFunction<*>) = when (getFunction.returnType.jvmErasure) {
+ Boolean::class -> (getFunction.call(defaultImpl) as Boolean?)?.not() ?: true
+ CharSequence::class,
+ String::class -> getFunction.name + "TEST"
+ Int::class -> testCounter++
+ Long::class -> (testCounter++).toLong()
+ Float::class -> (testCounter++).toFloat()
+ else -> {
+ expect.withMessage("${getFunction.name} needs to provide value").fail()
+ null
+ }
+ }
+
+ /**
+ * Verifies two instances are equivalent via a series of properties. For use when a public API
+ * class has not implemented equals.
+ */
+ @Suppress("UNCHECKED_CAST")
+ protected fun <T : Any> equalBy(
+ first: T?,
+ second: T?,
+ vararg properties: (T) -> Any?
+ ) = properties.all { property ->
+ first?.let { property(it) } == second?.let { property(it) }
+ }
+
+ @Test
+ fun valueComparison() {
+ val params = baseParams.mapNotNull(::buildParams) + extraParams().filterNotNull()
+ val before = initialObject()
+
+ params.forEach { it.setFunction(arrayOf(before, it.value())) }
+
+ val parcel = Parcel.obtain()
+ writeToParcel(parcel, before)
+
+ val dataSize = parcel.dataSize()
+
+ parcel.setDataPosition(0)
+
+ val after = creator.createFromParcel(parcel)
+
+ expect.withMessage("Mismatched write and read data sizes")
+ .that(parcel.dataPosition())
+ .isEqualTo(dataSize)
+
+ parcel.recycle()
+
+ runAssertions(params, before, after)
+ }
+
+ @Test
+ open fun parcellingSize() {
+ val parcelOne = Parcel.obtain()
+ writeToParcel(parcelOne, initialObject())
+
+ val parcelTwo = Parcel.obtain()
+ initialObject().writeToParcel(parcelTwo, 0)
+
+ val superDataSizes = setterType.allSuperclasses
+ .filter { it.isSubclassOf(Parcelable::class) }
+ .mapNotNull { it.memberFunctions.find { it.name == "writeToParcel" } }
+ .filter { it.isFinal }
+ .map {
+ val parcel = Parcel.obtain()
+ initialObject().writeToParcel(parcel, 0)
+ parcel.dataSize().also { parcel.recycle() }
+ }
+
+ if ((superDataSizes + parcelOne.dataSize() + parcelTwo.dataSize()).distinct().size != 1) {
+ listOf(getterType, setterType).distinct().forEach {
+ val creatorProperties = it.staticProperties.filter { it.name == "CREATOR" }
+ if (creatorProperties.size > 1) {
+ expect.withMessage(
+ "Multiple matching CREATOR fields found for" +
+ it.qualifiedName
+ )
+ .that(creatorProperties)
+ .hasSize(1)
+ } else {
+ val creator = creatorProperties.single().get()
+ if (creator !is Parcelable.Creator<*>) {
+ expect.that(creator).isInstanceOf(Parcelable.Creator::class.java)
+ return
+ }
+
+ parcelTwo.setDataPosition(0)
+ val parcelable = creator.createFromParcel(parcelTwo)
+ if (parcelable::class.isSubclassOf(setterType)) {
+ expect.withMessage(
+ "${it.qualifiedName} which does not safely override writeToParcel " +
+ "cannot contain a subclass CREATOR field"
+ )
+ .fail()
+ }
+ }
+ }
+ }
+
+ parcelOne.recycle()
+ parcelTwo.recycle()
+ }
+
+ private fun runAssertions(params: List<Param>, before: Parcelable, after: Parcelable) {
+ params.forEach {
+ val actual = it.getFunction(after)
+ val expected = it.value()
+ val equal = it.compare(actual, expected)
+ expect.withMessage("${it.getFunctionName} was $actual, expected $expected")
+ .that(equal)
+ .isTrue()
+ }
+
+ extraAssertions(before, after)
+
+ // TODO: Handle method overloads?
+ val expectedFunctions = (getters.map { it.name }
+ + setters.map { it.name }
+ - excludedMethods)
+ .distinct()
+
+ val allTestedFunctions = params.flatMap {
+ listOfNotNull(it.getFunctionName, it.setFunctionName)
+ }
+ expect.that(allTestedFunctions).containsExactlyElementsIn(expectedFunctions)
+ }
+
+ open fun extraParams(): Collection<Param?> = emptyList()
+
+ open fun initialObject(): Parcelable = setterType.createInstance()
+
+ open fun extraAssertions(before: Parcelable, after: Parcelable) {}
+
+ open fun writeToParcel(parcel: Parcel, value: Parcelable) = value.writeToParcel(parcel, 0)
+
+ data class Param(
+ val getFunctionName: String,
+ val getFunction: (Any?) -> Any?,
+ val setFunctionName: String?,
+ val setFunction: (Array<Any?>) -> Unit,
+ val value: () -> Any?,
+ val compare: (Any?, Any?) -> Boolean = Objects::equals
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt
new file mode 100644
index 0000000..d506190
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.parsing.parcelling.java.TestSubWithCreator
+import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
+import org.junit.Test
+import kotlin.contracts.ExperimentalContracts
+
+/**
+ * Verifies the failing side of [ParcelableCreatorValidTest]. The sole difference is the addition
+ * of [TestSubWithCreator.CREATOR].
+ */
+@ExperimentalContracts
+class ParcelableCreatorInvalidTest :
+ ParcelableComponentTest(TestSuperClass::class, TestSubWithCreator::class) {
+
+ override val defaultImpl = TestSubWithCreator()
+
+ override val creator = object : Parcelable.Creator<Parcelable> {
+ override fun createFromParcel(source: Parcel) = TestSubWithCreator(source)
+ override fun newArray(size: Int) = Array<TestSubWithCreator?>(size) { null }
+ }
+
+ override val excludedMethods = listOf("writeSubToParcel")
+
+ override val baseParams = listOf(TestSuperClass::getSuperString)
+
+ override fun writeToParcel(parcel: Parcel, value: Parcelable) {
+ (value as TestSubWithCreator).writeSubToParcel(parcel, 0)
+ }
+
+ @Test
+ override fun parcellingSize() {
+ super.parcellingSize()
+ if (expect.hasFailures()) {
+ // This is a hack to ignore an expected failure result. Doing it this way, rather than
+ // adding a switch in the test itself, prevents it from accidentally passing through a
+ // programming error.
+ ignoreableExpect.ignore()
+ }
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt
new file mode 100644
index 0000000..f1bc7b5
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.parsing.parcelling.java.TestSubWithoutCreator
+import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
+import kotlin.contracts.ExperimentalContracts
+
+/**
+ * Tests the [Parcelable] CREATOR verification by using a mock object with known differences to
+ * ensure that the method succeeds/fails.
+ */
+@ExperimentalContracts
+class ParcelableCreatorValidTest :
+ ParcelableComponentTest(TestSuperClass::class, TestSubWithoutCreator::class) {
+
+ override val defaultImpl = TestSubWithoutCreator()
+
+ override val creator = object : Parcelable.Creator<Parcelable> {
+ override fun createFromParcel(source: Parcel) = TestSubWithoutCreator(source)
+ override fun newArray(size: Int) = Array<TestSubWithoutCreator?>(size) { null }
+ }
+
+ override val excludedMethods = listOf("writeSubToParcel")
+
+ override val baseParams = listOf(TestSuperClass::getSuperString)
+
+ override fun writeToParcel(parcel: Parcel, value: Parcelable) {
+ (value as TestSubWithoutCreator).writeSubToParcel(parcel, 0)
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
new file mode 100644
index 0000000..ece600b
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.ActivityInfo
+import android.content.pm.parsing.component.ParsedActivity
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedActivityTest : ParsedMainComponentTest(ParsedActivity::class) {
+
+ override val defaultImpl = ParsedActivity()
+ override val creator = ParsedActivity.CREATOR
+
+ override val mainComponentSubclassBaseParams = listOf(
+ ParsedActivity::getPermission,
+ ParsedActivity::getColorMode,
+ ParsedActivity::getConfigChanges,
+ ParsedActivity::getDocumentLaunchMode,
+ ParsedActivity::getLaunchMode,
+ ParsedActivity::getLockTaskLaunchMode,
+ ParsedActivity::getMaxAspectRatio,
+ ParsedActivity::getMaxRecents,
+ ParsedActivity::getMinAspectRatio,
+ ParsedActivity::getParentActivityName,
+ ParsedActivity::getPersistableMode,
+ ParsedActivity::getPrivateFlags,
+ ParsedActivity::getRequestedVrComponent,
+ ParsedActivity::getResizeMode,
+ ParsedActivity::getRotationAnimation,
+ ParsedActivity::getScreenOrientation,
+ ParsedActivity::getSoftInputMode,
+ ParsedActivity::getTargetActivity,
+ ParsedActivity::getTaskAffinity,
+ ParsedActivity::getTheme,
+ ParsedActivity::getUiOptions,
+ ParsedActivity::isSupportsSizeChanges,
+ )
+
+ override fun mainComponentSubclassExtraParams() = listOf(
+ getSetByValue(
+ ParsedActivity::getWindowLayout,
+ ParsedActivity::setWindowLayout,
+ ActivityInfo.WindowLayout(1, 1f, 2, 1f, 3, 4, 5),
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ ActivityInfo.WindowLayout::width,
+ ActivityInfo.WindowLayout::widthFraction,
+ ActivityInfo.WindowLayout::height,
+ ActivityInfo.WindowLayout::heightFraction,
+ ActivityInfo.WindowLayout::gravity,
+ ActivityInfo.WindowLayout::minWidth,
+ ActivityInfo.WindowLayout::minHeight
+ )
+ }
+ )
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
new file mode 100644
index 0000000..e739dc7
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedAttribution
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedAttributionTest : ParcelableComponentTest(ParsedAttribution::class) {
+
+ override val defaultImpl = ParsedAttribution("", 0, emptyList())
+ override val creator = ParsedAttribution.CREATOR
+
+ override val baseParams = listOf(
+ ParsedAttribution::getTag,
+ ParsedAttribution::getLabel,
+ )
+
+ override fun extraParams() = listOf(
+ getter(ParsedAttribution::getInheritFrom, listOf("testInheritFrom"))
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
new file mode 100644
index 0000000..0a22f6d
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.PackageManager
+import android.content.pm.parsing.component.ParsedComponent
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.os.Bundle
+import android.os.Parcelable
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction1
+
+@ExperimentalContracts
+abstract class ParsedComponentTest(kClass: KClass<out Parcelable>) :
+ ParcelableComponentTest(kClass) {
+
+ final override val excludedMethods
+ get() = subclassExcludedMethods + listOf(
+ // Method aliases/utilities
+ "getClassName",
+ "getComponentName",
+ "setProperties" // Tested though addProperty
+ )
+
+ open val subclassExcludedMethods: Collection<String> = emptyList()
+
+ final override val baseParams
+ get() = subclassBaseParams + listOf(
+ ParsedComponent::getBanner,
+ ParsedComponent::getDescriptionRes,
+ ParsedComponent::getFlags,
+ ParsedComponent::getIcon,
+ ParsedComponent::getLabelRes,
+ ParsedComponent::getLogo,
+ ParsedComponent::getName,
+ ParsedComponent::getNonLocalizedLabel,
+ ParsedComponent::getPackageName,
+ )
+
+ abstract val subclassBaseParams: Collection<KFunction1<*, Any?>>
+
+ final override fun extraParams() = subclassExtraParams() + listOf(
+ getSetByValue(
+ ParsedComponent::getIntents,
+ ParsedComponent::addIntent,
+ "TestLabel",
+ transformGet = { it.singleOrNull()?.nonLocalizedLabel },
+ transformSet = { ParsedIntentInfo().setNonLocalizedLabel(it) },
+ ),
+ getSetByValue(
+ ParsedComponent::getProperties,
+ ParsedComponent::addProperty,
+ PackageManager.Property(
+ "testPropertyName",
+ "testPropertyValue",
+ "testPropertyClassName",
+ "testPropertyPackageName"
+ ),
+ transformGet = { it["testPropertyName"] },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ PackageManager.Property::getName,
+ PackageManager.Property::getClassName,
+ PackageManager.Property::getPackageName,
+ PackageManager.Property::getString,
+ )
+ }
+ ),
+ getSetByValue(
+ ParsedComponent::getMetaData,
+ ParsedComponent::setMetaData,
+ "testBundleKey" to "testBundleValue",
+ transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
+ transformSet = { Bundle().apply { putString(it.first, it.second) } }
+ ),
+ )
+
+ open fun subclassExtraParams(): Collection<Param?> = emptyList()
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
new file mode 100644
index 0000000..b7a85cc
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedInstrumentation
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedInstrumentationTest : ParsedComponentTest(ParsedInstrumentation::class) {
+
+ override val defaultImpl = ParsedInstrumentation()
+ override val creator = ParsedInstrumentation.CREATOR
+
+ override val subclassBaseParams = listOf(
+ ParsedInstrumentation::getTargetPackage,
+ ParsedInstrumentation::getTargetProcesses,
+ ParsedInstrumentation::isFunctionalTest,
+ ParsedInstrumentation::isHandleProfiling,
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
new file mode 100644
index 0000000..e27bdf2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.os.Parcel
+import android.os.Parcelable
+import android.os.PatternMatcher
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedIntentInfoTest : ParcelableComponentTest(ParsedIntentInfo::class) {
+
+ override val defaultImpl = ParsedIntentInfo()
+
+ override val creator = object : Parcelable.Creator<ParsedIntentInfo> {
+ override fun createFromParcel(source: Parcel) = ParsedIntentInfo(source)
+ override fun newArray(size: Int) = Array<ParsedIntentInfo?>(size) { null }
+ }
+
+ override val excludedMethods = listOf(
+ // Used to parcel
+ "writeIntentInfoToParcel",
+ // All remaining IntentFilter methods, which are out of scope
+ "hasDataPath",
+ "hasDataSchemeSpecificPart",
+ "matchAction",
+ "matchData",
+ "actionsIterator",
+ "addAction",
+ "addCategory",
+ "addDataAuthority",
+ "addDataPath",
+ "addDataScheme",
+ "addDataSchemeSpecificPart",
+ "addDataType",
+ "addDynamicDataType",
+ "addMimeGroup",
+ "asPredicate",
+ "asPredicateWithTypeResolution",
+ "authoritiesIterator",
+ "categoriesIterator",
+ "clearDynamicDataTypes",
+ "countActions",
+ "countCategories",
+ "countDataAuthorities",
+ "countDataPaths",
+ "countDataSchemeSpecificParts",
+ "countDataSchemes",
+ "countDataTypes",
+ "countMimeGroups",
+ "countStaticDataTypes",
+ "dataTypes",
+ "debugCheck",
+ "dump",
+ "dumpDebug",
+ "getAction",
+ "getAutoVerify",
+ "getCategory",
+ "getDataAuthority",
+ "getDataPath",
+ "getDataScheme",
+ "getDataSchemeSpecificPart",
+ "getDataType",
+ "getHosts",
+ "getHostsList",
+ "getMimeGroup",
+ "getOrder",
+ "getPriority",
+ "getVisibilityToInstantApp",
+ "handleAllWebDataURI",
+ "handlesWebUris",
+ "hasAction",
+ "hasCategory",
+ "hasDataAuthority",
+ "hasDataScheme",
+ "hasDataType",
+ "hasExactDataType",
+ "hasExactDynamicDataType",
+ "hasExactStaticDataType",
+ "hasMimeGroup",
+ "isExplicitlyVisibleToInstantApp",
+ "isImplicitlyVisibleToInstantApp",
+ "isVerified",
+ "isVisibleToInstantApp",
+ "match",
+ "matchCategories",
+ "matchDataAuthority",
+ "mimeGroupsIterator",
+ "needsVerification",
+ "pathsIterator",
+ "readFromXml",
+ "schemeSpecificPartsIterator",
+ "schemesIterator",
+ "setAutoVerify",
+ "setOrder",
+ "setPriority",
+ "setVerified",
+ "setVisibilityToInstantApp",
+ "typesIterator",
+ "writeToXml",
+ )
+
+ override val baseParams = listOf(
+ ParsedIntentInfo::getIcon,
+ ParsedIntentInfo::getLabelRes,
+ ParsedIntentInfo::isHasDefault,
+ ParsedIntentInfo::getNonLocalizedLabel,
+ )
+
+ override fun initialObject() = ParsedIntentInfo().apply {
+ addAction("test.ACTION")
+ addDataAuthority("testAuthority", "404")
+ addCategory("test.CATEGORY")
+ addMimeGroup("testMime")
+ addDataPath("testPath", PatternMatcher.PATTERN_LITERAL)
+ }
+
+ override fun extraAssertions(before: Parcelable, after: Parcelable) {
+ super.extraAssertions(before, after)
+ after as ParsedIntentInfo
+ expect.that(after.actionsIterator().asSequence().singleOrNull())
+ .isEqualTo("test.ACTION")
+
+ val authority = after.authoritiesIterator().asSequence().singleOrNull()
+ expect.that(authority?.host).isEqualTo("testAuthority")
+ expect.that(authority?.port).isEqualTo(404)
+
+ expect.that(after.categoriesIterator().asSequence().singleOrNull())
+ .isEqualTo("test.CATEGORY")
+ expect.that(after.mimeGroupsIterator().asSequence().singleOrNull())
+ .isEqualTo("testMime")
+ expect.that(after.hasDataPath("testPath")).isTrue()
+ }
+
+ override fun writeToParcel(parcel: Parcel, value: Parcelable) =
+ ParsedIntentInfo.PARCELER.parcel(value as ParsedIntentInfo, parcel, 0)
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
new file mode 100644
index 0000000..411cb09
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedMainComponent
+import android.content.pm.parsing.component.ParsedService
+import android.os.Parcelable
+import java.util.Arrays
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction1
+
+@ExperimentalContracts
+abstract class ParsedMainComponentTest(kClass: KClass<out Parcelable>) :
+ ParsedComponentTest(kClass) {
+
+ final override val subclassBaseParams
+ get() = mainComponentSubclassBaseParams + listOf(
+ ParsedMainComponent::getOrder,
+ ParsedMainComponent::getProcessName,
+ ParsedMainComponent::getSplitName,
+ ParsedMainComponent::isDirectBootAware,
+ ParsedMainComponent::isEnabled,
+ ParsedMainComponent::isExported,
+ )
+
+ abstract val mainComponentSubclassBaseParams: Collection<KFunction1<*, Any?>>
+
+ final override fun subclassExtraParams() = mainComponentSubclassExtraParams() + listOf(
+ getSetByValue(
+ ParsedService::getAttributionTags,
+ ParsedService::setAttributionTags,
+ arrayOf("testAttributionTag"),
+ compare = Arrays::equals
+ ),
+ )
+
+ open fun mainComponentSubclassExtraParams(): Collection<Param?> = emptyList()
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
new file mode 100644
index 0000000..53c862a
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedPermissionGroupTest : ParsedComponentTest(ParsedPermissionGroup::class) {
+
+ override val defaultImpl = ParsedPermissionGroup()
+ override val creator = ParsedPermissionGroup.CREATOR
+
+ override val subclassBaseParams = listOf(
+ ParsedPermissionGroup::getRequestDetailResourceId,
+ ParsedPermissionGroup::getBackgroundRequestDetailResourceId,
+ ParsedPermissionGroup::getBackgroundRequestResourceId,
+ ParsedPermissionGroup::getRequestRes,
+ ParsedPermissionGroup::getPriority,
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
new file mode 100644
index 0000000..bb63e2e2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedPermission
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedPermissionTest : ParsedComponentTest(ParsedPermission::class) {
+
+ override val defaultImpl = ParsedPermission()
+ override val creator = ParsedPermission.CREATOR
+
+ override val subclassExcludedMethods = listOf(
+ // Utility methods
+ "isAppOp",
+ "isRuntime",
+ "getProtection",
+ "getProtectionFlags",
+ "calculateFootprint",
+ "setKnownCert", // Tested through setKnownCerts
+ )
+ override val subclassBaseParams = listOf(
+ ParsedPermission::getBackgroundPermission,
+ ParsedPermission::getGroup,
+ ParsedPermission::getRequestRes,
+ ParsedPermission::getProtectionLevel,
+ ParsedPermission::isTree,
+ )
+
+ override fun subclassExtraParams() = listOf(
+ getter(ParsedPermission::getKnownCerts, setOf("testCert")),
+ getSetByValue(
+ ParsedPermission::getParsedPermissionGroup,
+ ParsedPermission::setParsedPermissionGroup,
+ ParsedPermissionGroup().apply { name = "test.permission.group" },
+ compare = { first, second -> equalBy(first, second, ParsedPermissionGroup::getName) }
+ ),
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
new file mode 100644
index 0000000..34f46f2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedProcess
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedProcessTest : ParcelableComponentTest(ParsedProcess::class) {
+
+ override val defaultImpl = ParsedProcess()
+ override val creator = ParsedProcess.CREATOR
+
+ override val excludedMethods = listOf(
+ // Copying method
+ "addStateFrom",
+ )
+
+ override val baseParams = listOf(
+ ParsedProcess::getName,
+ ParsedProcess::getGwpAsanMode,
+ ParsedProcess::getMemtagMode,
+ ParsedProcess::getNativeHeapZeroInitialized,
+ )
+
+ override fun extraParams() = listOf(
+ getter(ParsedProcess::getDeniedPermissions, setOf("testDeniedPermission"))
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
new file mode 100644
index 0000000..e6d5c0f
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.PathPermission
+import android.content.pm.parsing.component.ParsedProvider
+import android.os.PatternMatcher
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedProviderTest : ParsedMainComponentTest(ParsedProvider::class) {
+
+ override val defaultImpl = ParsedProvider()
+ override val creator = ParsedProvider.CREATOR
+
+ override val mainComponentSubclassBaseParams = listOf(
+ ParsedProvider::getAuthority,
+ ParsedProvider::isSyncable,
+ ParsedProvider::getReadPermission,
+ ParsedProvider::getWritePermission,
+ ParsedProvider::isGrantUriPermissions,
+ ParsedProvider::isForceUriPermissions,
+ ParsedProvider::isMultiProcess,
+ ParsedProvider::getInitOrder,
+ )
+
+ override fun mainComponentSubclassExtraParams() = listOf(
+ getSetByValue(
+ ParsedProvider::getUriPermissionPatterns,
+ ParsedProvider::setUriPermissionPatterns,
+ PatternMatcher("testPattern", PatternMatcher.PATTERN_LITERAL),
+ transformGet = { it?.singleOrNull() },
+ transformSet = { arrayOf(it) },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ PatternMatcher::getPath,
+ PatternMatcher::getType
+ )
+ }
+ ),
+ getSetByValue(
+ ParsedProvider::getPathPermissions,
+ ParsedProvider::setPathPermissions,
+ PathPermission(
+ "testPermissionPattern",
+ PatternMatcher.PATTERN_LITERAL,
+ "test.READ_PERMISSION",
+ "test.WRITE_PERMISSION"
+ ),
+ transformGet = { it?.singleOrNull() },
+ transformSet = { arrayOf(it) },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ PatternMatcher::getPath,
+ PatternMatcher::getType,
+ PathPermission::getReadPermission,
+ PathPermission::getWritePermission,
+ )
+ }
+ )
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
new file mode 100644
index 0000000..5530184
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedService
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedServiceTest : ParsedMainComponentTest(ParsedService::class) {
+
+ override val defaultImpl = ParsedService()
+ override val creator = ParsedService.CREATOR
+
+ override val mainComponentSubclassBaseParams = listOf(
+ ParsedService::getForegroundServiceType,
+ ParsedService::getPermission,
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
new file mode 100644
index 0000000..1131c72
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedUsesPermission
+import android.os.Parcelable
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedUsesPermissionTest : ParcelableComponentTest(ParsedUsesPermission::class) {
+
+ override val defaultImpl = ParsedUsesPermission("", 0)
+ override val creator = ParsedUsesPermission.CREATOR
+
+ override val baseParams = listOf(
+ ParsedUsesPermission::getName,
+ ParsedUsesPermission::getUsesPermissionFlags
+ )
+
+ override fun initialObject() = ParsedUsesPermission("", 0)
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java
new file mode 100644
index 0000000..581d2b2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling.java;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+public class TestSubWithCreator extends TestSuperClass {
+
+ @NonNull
+ public static final Parcelable.Creator<TestSubWithCreator> CREATOR =
+ new Parcelable.Creator<TestSubWithCreator>() {
+ @Override
+ public TestSubWithCreator createFromParcel(Parcel source) {
+ return new TestSubWithCreator(source);
+ }
+
+ @Override
+ public TestSubWithCreator[] newArray(int size) {
+ return new TestSubWithCreator[size];
+ }
+ };
+
+ @Nullable
+ private String subString;
+
+ public TestSubWithCreator() {
+ }
+
+ public TestSubWithCreator(@NonNull Parcel in) {
+ super(in);
+ subString = in.readString();
+ }
+
+ public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
+ super.writeToParcel(parcel, flags);
+ parcel.writeString(subString);
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java
new file mode 100644
index 0000000..4264a11
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling.java;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+
+import androidx.annotation.NonNull;
+
+public class TestSubWithoutCreator extends TestSuperClass {
+
+ @Nullable
+ private String subString;
+
+ public TestSubWithoutCreator() {
+ }
+
+ public TestSubWithoutCreator(@NonNull Parcel in) {
+ super(in);
+ subString = in.readString();
+ }
+
+ public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
+ super.writeToParcel(parcel, flags);
+ parcel.writeString(subString);
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
new file mode 100644
index 0000000..a009786
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling.java;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+@DataClass(genGetters = true, genSetters = true, genBuilder = false, genAidl = false,
+ genParcelable = true, genConstructor = false)
+public class TestSuperClass implements Parcelable {
+
+ @Nullable
+ private String superString;
+
+ public TestSuperClass() {
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public @Nullable String getSuperString() {
+ return superString;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull TestSuperClass setSuperString(@NonNull String value) {
+ superString = value;
+ return this;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (superString != null) flg |= 0x1;
+ dest.writeByte(flg);
+ if (superString != null) dest.writeString(superString);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected TestSuperClass(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ String _superString = (flg & 0x1) == 0 ? null : in.readString();
+
+ this.superString = _superString;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<TestSuperClass> CREATOR
+ = new Parcelable.Creator<TestSuperClass>() {
+ @Override
+ public TestSuperClass[] newArray(int size) {
+ return new TestSuperClass[size];
+ }
+
+ @Override
+ public TestSuperClass createFromParcel(@NonNull android.os.Parcel in) {
+ return new TestSuperClass(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1624381019144L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java",
+ inputSignatures = "private @android.annotation.Nullable java.lang.String superString\nclass TestSuperClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genAidl=false, genParcelable=true, genConstructor=false)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt
new file mode 100644
index 0000000..afb18f5
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.pm.test.util
+
+import com.google.common.truth.Expect
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * Wrapper for [Expect] which supports ignoring any failures. This should be used with caution, but
+ * it allows a base test to be written which doesn't switch success/failure in the test itself,
+ * preventing any logic errors from causing the test to accidentally succeed.
+ */
+internal class IgnoreableExpect : TestRule {
+
+ val expect = Expect.create()
+
+ private var ignore = false
+
+ override fun apply(base: Statement?, description: Description?): Statement {
+ return object : Statement() {
+ override fun evaluate() {
+ ignore = false
+ try {
+ expect.apply(base, description).evaluate()
+ } catch (t: Throwable) {
+ if (!ignore) {
+ throw t
+ }
+ }
+ }
+ }
+ }
+
+ fun ignore() {
+ ignore = true
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index a205a1d..1ac28ab 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -1340,11 +1340,19 @@
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
director.start(createMockSensorManager());
- ArgumentCaptor<ProximityActiveListener> captor =
+ ArgumentCaptor<ProximityActiveListener> ProximityCaptor =
ArgumentCaptor.forClass(ProximityActiveListener.class);
verify(mSensorManagerInternalMock).addProximityActiveListener(any(Executor.class),
- captor.capture());
- ProximityActiveListener listener = captor.getValue();
+ ProximityCaptor.capture());
+ ProximityActiveListener proximityListener = ProximityCaptor.getValue();
+
+ ArgumentCaptor<DisplayListener> DisplayCaptor =
+ ArgumentCaptor.forClass(DisplayListener.class);
+ verify(mInjector).registerDisplayListener(DisplayCaptor.capture(), any(Handler.class),
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+ DisplayListener displayListener = DisplayCaptor.getValue();
// Verify that there is no proximity vote initially
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
@@ -1353,13 +1361,38 @@
when(mDisplayManagerInternalMock.getRefreshRateForDisplayAndSensor(eq(DISPLAY_ID), eq(null),
eq(Sensor.STRING_TYPE_PROXIMITY))).thenReturn(new RefreshRateRange(60, 60));
+ when(mInjector.isDozeState(any(Display.class))).thenReturn(false);
+
// Set the proximity to active and verify that we added a vote.
- listener.onProximityActive(true);
+ proximityListener.onProximityActive(true);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertVoteForRefreshRate(vote, 60.f);
+
+ // Set the display state to doze and verify that the vote is gone
+ when(mInjector.isDozeState(any(Display.class))).thenReturn(true);
+ displayListener.onDisplayAdded(DISPLAY_ID);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertNull(vote);
+
+ // Set the display state to on and verify that we added the vote back.
+ when(mInjector.isDozeState(any(Display.class))).thenReturn(false);
+ displayListener.onDisplayChanged(DISPLAY_ID);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertVoteForRefreshRate(vote, 60.f);
+
+ // Set the display state to doze and verify that the vote is gone
+ when(mInjector.isDozeState(any(Display.class))).thenReturn(true);
+ displayListener.onDisplayAdded(DISPLAY_ID);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertNull(vote);
+
+ // Remove the display to cause the doze state to be removed
+ displayListener.onDisplayRemoved(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
assertVoteForRefreshRate(vote, 60.f);
// Turn prox off and verify vote is gone.
- listener.onProximityActive(false);
+ proximityListener.onProximityActive(false);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
assertNull(vote);
}
@@ -1710,6 +1743,11 @@
return null;
}
+ @Override
+ public boolean isDozeState(Display d) {
+ return false;
+ }
+
void notifyPeakRefreshRateChanged() {
if (mPeakRefreshRateObserver != null) {
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
new file mode 100644
index 0000000..00e3bf1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2021 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.hdmi;
+
+import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.hdmi.RequestSadAction.RequestSadCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public class RequestSadActionTest {
+
+ private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
+ private static final ArrayList<Integer> CODECS_TO_QUERY_1 = new ArrayList<Integer>(
+ Arrays.asList(Constants.AUDIO_CODEC_LPCM, Constants.AUDIO_CODEC_DD,
+ Constants.AUDIO_CODEC_MPEG1, Constants.AUDIO_CODEC_MP3));
+ private static final ArrayList<Integer> CODECS_TO_QUERY_2 = new ArrayList<Integer>(
+ Arrays.asList(Constants.AUDIO_CODEC_MPEG2, Constants.AUDIO_CODEC_AAC,
+ Constants.AUDIO_CODEC_DTS, Constants.AUDIO_CODEC_ATRAC));
+ private static final ArrayList<Integer> CODECS_TO_QUERY_3 = new ArrayList<Integer>(
+ Arrays.asList(Constants.AUDIO_CODEC_ONEBITAUDIO, Constants.AUDIO_CODEC_DDP,
+ Constants.AUDIO_CODEC_DTSHD, Constants.AUDIO_CODEC_TRUEHD));
+ private static final ArrayList<Integer> CODECS_TO_QUERY_4 = new ArrayList<Integer>(
+ Arrays.asList(Constants.AUDIO_CODEC_DST, Constants.AUDIO_CODEC_WMAPRO,
+ Constants.AUDIO_CODEC_MAX));
+
+ private HdmiControlService mHdmiControlService;
+ private HdmiCecController mHdmiCecController;
+ private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
+ private FakeNativeWrapper mNativeWrapper;
+ private Looper mMyLooper;
+ private TestLooper mTestLooper = new TestLooper();
+ private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+ private List<byte[]> mSupportedSads;
+ private RequestSadCallback mCallback =
+ new RequestSadCallback() {
+ @Override
+ public void onRequestSadDone(
+ List<byte[]> supportedSads) {
+ mSupportedSads = supportedSads;
+ }
+ };
+ @Mock
+ private IPowerManager mIPowerManagerMock;
+ @Mock
+ private IThermalService mIThermalServiceMock;
+
+ private static byte[] concatenateSads(List<byte[]> sads) {
+ byte[] concatenatedSads = new byte[sads.size() * 3];
+ for (int i = 0; i < sads.size(); i++) {
+ for (int j = 0; j < 3; j++) {
+ concatenatedSads[3 * i + j] = sads.get(i)[j];
+ }
+ }
+ return concatenatedSads;
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ Context context = InstrumentationRegistry.getTargetContext();
+ mMyLooper = mTestLooper.getLooper();
+
+ mHdmiControlService =
+ new HdmiControlService(InstrumentationRegistry.getTargetContext(),
+ Collections.emptyList()) {
+ @Override
+ boolean isControlEnabled() {
+ return true;
+ }
+
+ @Override
+ void wakeUp() {
+ }
+
+ @Override
+ protected void writeStringSystemProperty(String key, String value) {
+ // do nothing
+ }
+
+ @Override
+ boolean isPowerStandbyOrTransient() {
+ return false;
+ }
+
+ @Override
+ protected PowerManager getPowerManager() {
+ return new PowerManager(context, mIPowerManagerMock,
+ mIThermalServiceMock, new Handler(mMyLooper));
+ }
+ };
+
+ mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
+ mHdmiCecLocalDeviceTv.init();
+ mHdmiControlService.setIoLooper(mMyLooper);
+ mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
+ mNativeWrapper = new FakeNativeWrapper();
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
+ mHdmiControlService.setCecController(mHdmiCecController);
+ mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+ mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+ mLocalDevices.add(mHdmiCecLocalDeviceTv);
+ mHdmiControlService.initService();
+ mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mNativeWrapper.setPhysicalAddress(0x0000);
+ mTestLooper.dispatchAll();
+ mNativeWrapper.clearResultMessages();
+ }
+
+ @Test
+ public void noResponse_queryAgain_emptyResult() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void featureAbort_dontQueryAgain_emptyResult() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+ HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR,
+ Constants.ABORT_INVALID_OPERAND);
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(featureAbort);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(featureAbort);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(featureAbort);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ action.processCommand(featureAbort);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void allSupported_completeResult() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_1 = new byte[]{
+ 0x01, 0x18, 0x4A,
+ 0x02, 0x64, 0x5A,
+ 0x03, 0x4B, 0x00,
+ 0x04, 0x20, 0x0A};
+ HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response1);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_2 = new byte[]{
+ 0x05, 0x18, 0x4A,
+ 0x06, 0x64, 0x5A,
+ 0x07, 0x4B, 0x00,
+ 0x08, 0x20, 0x0A};
+ HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response2);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_3 = new byte[]{
+ 0x09, 0x18, 0x4A,
+ 0x0A, 0x64, 0x5A,
+ 0x0B, 0x4B, 0x00,
+ 0x0C, 0x20, 0x0A};
+ HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response3);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_4 = new byte[]{
+ 0x0D, 0x18, 0x4A,
+ 0x0E, 0x64, 0x5A,
+ 0x0F, 0x4B, 0x00};
+ HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ action.processCommand(response4);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(15);
+ assertThat(Arrays.equals(sadsToRespond_1,
+ concatenateSads(mSupportedSads.subList(0, 4)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_2,
+ concatenateSads(mSupportedSads.subList(4, 8)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_3,
+ concatenateSads(mSupportedSads.subList(8, 12)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_4,
+ concatenateSads(mSupportedSads.subList(12, 15)))).isTrue();
+ }
+
+ @Test
+ public void subsetSupported_subsetResult() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_1 = new byte[]{
+ 0x01, 0x18, 0x4A,
+ 0x03, 0x4B, 0x00,
+ 0x04, 0x20, 0x0A};
+ HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response1);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_2 = new byte[]{
+ 0x08, 0x20, 0x0A};
+ HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response2);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_3 = new byte[]{
+ 0x09, 0x18, 0x4A,
+ 0x0A, 0x64, 0x5A,
+ 0x0B, 0x4B, 0x00,
+ 0x0C, 0x20, 0x0A};
+ HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response3);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_4 = new byte[]{
+ 0x0F, 0x4B, 0x00};
+ HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ action.processCommand(response4);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(9);
+ assertThat(Arrays.equals(sadsToRespond_1,
+ concatenateSads(mSupportedSads.subList(0, 3)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_2,
+ concatenateSads(mSupportedSads.subList(3, 4)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_3,
+ concatenateSads(mSupportedSads.subList(4, 8)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_4,
+ concatenateSads(mSupportedSads.subList(8, 9)))).isTrue();
+ }
+
+ @Test
+ public void invalidCodecs_emptyResults() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_1 = new byte[]{
+ 0x20, 0x18, 0x4A,
+ 0x21, 0x64, 0x5A,
+ 0x22, 0x4B, 0x00,
+ 0x23, 0x20, 0x0A};
+ HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response1);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_2 = new byte[]{
+ 0x24, 0x18, 0x4A,
+ 0x25, 0x64, 0x5A,
+ 0x26, 0x4B, 0x00,
+ 0x27, 0x20, 0x0A};
+ HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response2);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_3 = new byte[]{
+ 0x28, 0x18, 0x4A,
+ 0x29, 0x64, 0x5A,
+ 0x2A, 0x4B, 0x00,
+ 0x2B, 0x20, 0x0A};
+ HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response3);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_4 = new byte[]{
+ 0x2C, 0x18, 0x4A,
+ 0x2D, 0x64, 0x5A,
+ 0x2E, 0x4B, 0x00};
+ HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ action.processCommand(response4);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void invalidMessageLength_queryAgain() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_1 = new byte[]{
+ 0x01, 0x18,
+ 0x02, 0x64, 0x5A,
+ 0x03, 0x4B, 0x00,
+ 0x04, 0x20, 0x0A};
+ HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response1);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_2 = new byte[]{
+ 0x05, 0x18, 0x4A,
+ 0x06, 0x64, 0x5A,
+ 0x07,
+ 0x08, 0x20, 0x0A};
+ HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response2);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_3 = new byte[0];
+ HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response3);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_4 = new byte[]{
+ 0x0D, 0x18, 0x4A,
+ 0x0E, 0x64, 0x5A,
+ 0x0F, 0x4B};
+ HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response4);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(0);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 8b8a7e6..2bda120 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -40,6 +40,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -232,6 +233,21 @@
}
@Test
+ public void testGetStagedApexInfos_throwRunTimeException() throws RemoteException {
+ doThrow(RemoteException.class).when(mApexService).getStagedApexInfos(any());
+
+ assertThrows(RuntimeException.class,
+ () -> mApexManager.getStagedApexInfos(testParamsWithChildren()));
+ }
+
+ @Test
+ public void testGetStagedApexInfos_returnsEmptyArrayOnError() throws RemoteException {
+ doThrow(ServiceSpecificException.class).when(mApexService).getStagedApexInfos(any());
+
+ assertThat(mApexManager.getStagedApexInfos(testParamsWithChildren())).hasLength(0);
+ }
+
+ @Test
public void testMarkStagedSessionReady_throwPackageManagerException() throws RemoteException {
doAnswer(invocation -> {
throw new Exception();
diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS
index e15b5f5..2f51994 100644
--- a/services/tests/servicestests/src/com/android/server/pm/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS
@@ -1,3 +1,7 @@
include /services/core/java/com/android/server/pm/OWNERS
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+
+# apex support
+per-file ApexManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
+
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index e8c5fb3..38b98ca 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -949,7 +949,7 @@
.addConfigPreference(new ConfigurationInfo())
.addReqFeature(new FeatureInfo())
.addFeatureGroup(new FeatureGroupInfo())
- .setCompileSdkVersionCodename("foo23")
+ .setCompileSdkVersionCodeName("foo23")
.setCompileSdkVersion(100)
.setOverlayCategory("foo24")
.setOverlayIsStatic(true)
diff --git a/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java b/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
index 65a9759..4a25323 100644
--- a/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
+++ b/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
@@ -19,19 +19,31 @@
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
+
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.time.Clock;
+import java.time.ZoneOffset;
+
/** Test that the ledger records transactions correctly. */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LedgerTest {
+ @Before
+ public void setUp() {
+ TareUtils.sSystemClock = Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
+ }
+
@Test
public void testInitialState() {
final Ledger ledger = new Ledger();
@@ -72,4 +84,45 @@
assertEquals(1, ledger.get24HourSum(1, 27 * HOUR_IN_MILLIS));
assertEquals(0, ledger.get24HourSum(1, 28 * HOUR_IN_MILLIS));
}
+
+ @Test
+ public void testRemoveOldTransactions() {
+ final Ledger ledger = new Ledger();
+ ledger.removeOldTransactions(24 * HOUR_IN_MILLIS);
+ assertNull(ledger.getEarliestTransaction());
+
+ final long now = getCurrentTimeMillis();
+ Ledger.Transaction transaction1 = new Ledger.Transaction(
+ now - 48 * HOUR_IN_MILLIS, now - 40 * HOUR_IN_MILLIS, 1, null, 4800);
+ Ledger.Transaction transaction2 = new Ledger.Transaction(
+ now - 24 * HOUR_IN_MILLIS, now - 23 * HOUR_IN_MILLIS, 1, null, 600);
+ Ledger.Transaction transaction3 = new Ledger.Transaction(
+ now - 22 * HOUR_IN_MILLIS, now - 21 * HOUR_IN_MILLIS, 1, null, 600);
+ // Instant event
+ Ledger.Transaction transaction4 = new Ledger.Transaction(
+ now - 20 * HOUR_IN_MILLIS, now - 20 * HOUR_IN_MILLIS, 1, null, 500);
+ // Recent event
+ Ledger.Transaction transaction5 = new Ledger.Transaction(
+ now - 5 * MINUTE_IN_MILLIS, now - MINUTE_IN_MILLIS, 1, null, 400);
+ ledger.recordTransaction(transaction1);
+ ledger.recordTransaction(transaction2);
+ ledger.recordTransaction(transaction3);
+ ledger.recordTransaction(transaction4);
+ ledger.recordTransaction(transaction5);
+
+ assertEquals(transaction1, ledger.getEarliestTransaction());
+ ledger.removeOldTransactions(24 * HOUR_IN_MILLIS);
+ assertEquals(transaction2, ledger.getEarliestTransaction());
+ ledger.removeOldTransactions(23 * HOUR_IN_MILLIS);
+ assertEquals(transaction3, ledger.getEarliestTransaction());
+ // Shouldn't delete transaction3 yet since there's still a piece of it within the min age
+ // window.
+ ledger.removeOldTransactions(21 * HOUR_IN_MILLIS + 30 * MINUTE_IN_MILLIS);
+ assertEquals(transaction3, ledger.getEarliestTransaction());
+ // Instant event should be removed as soon as we hit the exact threshold.
+ ledger.removeOldTransactions(20 * HOUR_IN_MILLIS);
+ assertEquals(transaction5, ledger.getEarliestTransaction());
+ ledger.removeOldTransactions(0);
+ assertNull(ledger.getEarliestTransaction());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index 61b5c2b..4cc4d55 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -83,7 +83,7 @@
@Presubmit
public class VibrationThreadTest {
- private static final int TEST_TIMEOUT_MILLIS = 1_000;
+ private static final int TEST_TIMEOUT_MILLIS = 900;
private static final int UID = Process.ROOT_UID;
private static final int VIBRATOR_ID = 1;
private static final String PACKAGE_NAME = "package";
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 41f2246..54406c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1616,6 +1616,21 @@
}
@Test
+ public void testRemoveImmediatelyWithFinishingActivity() throws RemoteException {
+ final ActivityRecord activity = createActivityWithTask();
+ final WindowProcessController wpc = activity.app;
+ activity.makeFinishingLocked();
+ assertTrue(activity.finishing);
+
+ activity.getTask().removeImmediately("test");
+
+ verify(mAtm.getLifecycleManager()).scheduleTransaction(any(), eq(activity.appToken),
+ isA(DestroyActivityItem.class));
+ assertFalse(wpc.hasActivities());
+ assertEquals(DESTROYING, activity.getState());
+ }
+
+ @Test
public void testRemoveFromHistory() {
final ActivityRecord activity = createActivityWithTask();
final Task rootTask = activity.getRootTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index aa56183..17288c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -53,9 +53,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW;
import static com.google.common.truth.Truth.assertThat;
@@ -895,36 +892,6 @@
assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
}
- @UseTestDisplay(addWindows = W_INPUT_METHOD)
- @Test
- public void testAdjustImeInsetsVisibilityWhenTaskSwitchIsAnimating() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
- final InsetsStateController controller = mDisplayContent.getInsetsStateController();
- controller.getImeSourceProvider().setWindow(mImeWindow, null, null);
-
- // Simulate app requests IME with updating all windows Insets State when IME is above app.
- mDisplayContent.setImeLayeringTarget(app);
- mDisplayContent.setImeInputTarget(app);
- assertTrue(mDisplayContent.shouldImeAttachedToApp());
- controller.getImeSourceProvider().scheduleShowImePostLayout(app);
- controller.getImeSourceProvider().getSource().setVisible(true);
- controller.updateAboveInsetsState(mImeWindow, false);
-
- // Simulate task switching animation happens when switching app to app2.
- spyOn(app);
- spyOn(app2);
- doReturn(true).when(app).isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS);
- doReturn(true).when(app2).isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS);
- app.mActivityRecord.mLastImeShown = true;
-
- // Verify the IME insets is visible on app, but not for app2 during task animating.
- InsetsState stateApp = app.getInsetsState();
- InsetsState stateApp2 = app2.getInsetsState();
- assertTrue(stateApp.getSource(ITYPE_IME).isVisible());
- assertFalse(stateApp2.getSource(ITYPE_IME).isVisible());
- }
-
@UseTestDisplay(addWindows = { W_ACTIVITY })
@Test
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 965f126..734172f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -36,6 +36,7 @@
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
import android.media.AudioFormat;
+import android.media.AudioManagerInternal;
import android.media.permission.Identity;
import android.media.permission.PermissionUtil;
import android.os.Binder;
@@ -44,6 +45,7 @@
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SharedMemory;
@@ -275,6 +277,7 @@
LocalServices.getService(PermissionManagerServiceInternal.class)
.setHotwordDetectionServiceProvider(null);
mIdentity = null;
+ updateServiceUidForAudioPolicy(Process.INVALID_UID);
}
mCancellationTaskFuture.cancel(/* may interrupt */ true);
if (mAudioFlinger != null) {
@@ -893,6 +896,8 @@
connection.run(service -> service.ping(new IRemoteCallback.Stub() {
@Override
public void sendResult(Bundle bundle) throws RemoteException {
+ // TODO: Exit if the service has been unbound already (though there's a very low
+ // chance this happens).
if (DEBUG) {
Slog.d(TAG, "updating hotword UID " + Binder.getCallingUid());
}
@@ -902,10 +907,21 @@
LocalServices.getService(PermissionManagerServiceInternal.class)
.setHotwordDetectionServiceProvider(() -> uid);
mIdentity = new HotwordDetectionServiceIdentity(uid, mVoiceInteractionServiceUid);
+ updateServiceUidForAudioPolicy(uid);
}
}));
}
+ private void updateServiceUidForAudioPolicy(int uid) {
+ mScheduledExecutorService.execute(() -> {
+ final AudioManagerInternal audioManager =
+ LocalServices.getService(AudioManagerInternal.class);
+ if (audioManager != null) {
+ audioManager.setHotwordDetectionServiceUid(uid);
+ }
+ });
+ }
+
private static void bestEffortClose(Closeable closeable) {
try {
closeable.close();
diff --git a/tests/InputMethodStressTest/Android.bp b/tests/InputMethodStressTest/Android.bp
new file mode 100644
index 0000000..131611d
--- /dev/null
+++ b/tests/InputMethodStressTest/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2021 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 {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "InputMethodStressTest",
+ srcs: ["src/**/*.java"],
+ libs: ["android.test.runner"],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.uiautomator_uiautomator",
+ "compatibility-device-util-axt",
+ "platform-test-annotations",
+ "truth-prebuilt",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ sdk_version: "31",
+}
diff --git a/tests/InputMethodStressTest/AndroidManifest.xml b/tests/InputMethodStressTest/AndroidManifest.xml
new file mode 100644
index 0000000..e5d6518
--- /dev/null
+++ b/tests/InputMethodStressTest/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.inputmethod.stresstest">
+
+ <application>
+ <activity android:name=".TestActivity"/>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.inputmethod.stresstest">
+ </instrumentation>
+</manifest>
diff --git a/tests/InputMethodStressTest/AndroidTest.xml b/tests/InputMethodStressTest/AndroidTest.xml
new file mode 100644
index 0000000..b194010
--- /dev/null
+++ b/tests/InputMethodStressTest/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="InputMethod integration/regression test">
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="InputMethodStressTest.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.inputmethod.stresstest" />
+ </test>
+</configuration>
diff --git a/tests/InputMethodStressTest/OWNERS b/tests/InputMethodStressTest/OWNERS
new file mode 100644
index 0000000..6bb4b17
--- /dev/null
+++ b/tests/InputMethodStressTest/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 34867
+
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java
new file mode 100644
index 0000000..5427fd8
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 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.inputmethod.stresstest;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.platform.test.annotations.RootPermissionTest;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+@RootPermissionTest
+@RunWith(AndroidJUnit4.class)
+public class ImeOpenCloseStressTest {
+
+ private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
+ private static final int NUM_TEST_ITERATIONS = 100;
+
+ private Instrumentation mInstrumentation;
+
+ @Test
+ public void test() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ Intent intent = new Intent()
+ .setAction(Intent.ACTION_MAIN)
+ .setClass(mInstrumentation.getContext(), TestActivity.class)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ TestActivity activity = (TestActivity) mInstrumentation.startActivitySync(intent);
+ eventually(() -> assertThat(callOnMainSync(activity::hasWindowFocus)).isTrue(), TIMEOUT);
+ for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
+ mInstrumentation.runOnMainSync(activity::showIme);
+ eventually(() -> assertThat(callOnMainSync(activity::isImeShown)).isTrue(), TIMEOUT);
+ mInstrumentation.runOnMainSync(activity::hideIme);
+ eventually(() -> assertThat(callOnMainSync(activity::isImeShown)).isFalse(), TIMEOUT);
+ }
+ }
+
+ private <V> V callOnMainSync(Callable<V> callable) {
+ AtomicReference<V> result = new AtomicReference<>();
+ AtomicReference<Exception> thrownException = new AtomicReference<>();
+ mInstrumentation.runOnMainSync(() -> {
+ try {
+ result.set(callable.call());
+ } catch (Exception e) {
+ thrownException.set(e);
+ }
+ });
+ if (thrownException.get() != null) {
+ throw new RuntimeException("Exception thrown from Main thread", thrownException.get());
+ }
+ return result.get();
+ }
+}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java b/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java
new file mode 100644
index 0000000..7baf037
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 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.inputmethod.stresstest;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowInsets;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+public class TestActivity extends Activity {
+
+ private EditText mEditText;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ LinearLayout rootView = new LinearLayout(this);
+ rootView.setOrientation(LinearLayout.VERTICAL);
+ mEditText = new EditText(this);
+ rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+ setContentView(rootView);
+ }
+
+ public boolean hasWindowFocus() {
+ return mEditText.hasWindowFocus();
+ }
+
+ public boolean isImeShown() {
+ WindowInsets insets = mEditText.getRootWindowInsets();
+ return insets.isVisible(WindowInsets.Type.ime());
+ }
+
+ public void showIme() {
+ mEditText.requestFocus();
+ InputMethodManager imm = getSystemService(InputMethodManager.class);
+ imm.showSoftInput(mEditText, 0);
+ }
+
+ public void hideIme() {
+ InputMethodManager imm = getSystemService(InputMethodManager.class);
+ imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
+ }
+}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 05c46ed..7a668a5 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -54,7 +54,6 @@
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -203,194 +202,6 @@
}
/**
- * Test that multiple available rollbacks are properly persisted.
- */
- @Test
- public void testAvailableRollbackPersistence() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- Uninstall.packages(TestApp.A);
- Install.single(TestApp.A1).commit();
- Install.single(TestApp.A2).setEnableRollback().commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
- Uninstall.packages(TestApp.B);
- Install.single(TestApp.B1).commit();
- Install.single(TestApp.B2).setEnableRollback().commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
- // Both test apps should now be available for rollback.
- RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A);
- assertThat(rollbackA).isNotNull();
- assertThat(rollbackA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1));
-
- RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B);
- assertThat(rollbackB).isNotNull();
- assertThat(rollbackB).packagesContainsExactly(
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Reload the persisted data.
- rm.reloadPersistedData();
-
- // The apps should still be available for rollback.
- rollbackA = waitForAvailableRollback(TestApp.A);
- assertThat(rollbackA).isNotNull();
- assertThat(rollbackA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1));
-
- rollbackB = waitForAvailableRollback(TestApp.B);
- assertThat(rollbackB).isNotNull();
- assertThat(rollbackB).packagesContainsExactly(
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Rollback of B should not rollback A
- RollbackUtils.rollback(rollbackB.getRollbackId());
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test that available multi-package rollbacks are properly persisted.
- */
- @Test
- public void testAvailableMultiPackageRollbackPersistence() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- Uninstall.packages(TestApp.A, TestApp.B);
- Install.multi(TestApp.A1, TestApp.B1).commit();
- Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
-
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
- // The app should now be available for rollback.
- RollbackInfo availableA = waitForAvailableRollback(TestApp.A);
- assertThat(availableA).isNotNull();
- assertThat(availableA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- RollbackInfo availableB = waitForAvailableRollback(TestApp.B);
- assertThat(availableB).isNotNull();
- assertThat(availableB).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Assert they're both the same rollback
- assertThat(availableA).hasRollbackId(availableB.getRollbackId());
-
- // Reload the persisted data.
- rm.reloadPersistedData();
-
- // The apps should still be available for rollback.
- availableA = waitForAvailableRollback(TestApp.A);
- assertThat(availableA).isNotNull();
- assertThat(availableA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- availableB = waitForAvailableRollback(TestApp.B);
- assertThat(availableB).isNotNull();
- assertThat(availableB).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Rollback of B should rollback A as well
- RollbackUtils.rollback(availableB.getRollbackId());
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-
- RollbackInfo committedA = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
- assertThat(committedA).isNotNull();
- assertThat(committedA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- RollbackInfo committedB = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
- assertThat(committedB).isNotNull();
- assertThat(committedB).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Assert they're both the same rollback
- assertThat(committedA).hasRollbackId(committedB.getRollbackId());
- assertThat(committedA).hasRollbackId(availableA.getRollbackId());
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test that recently committed rollback data is properly persisted.
- */
- @Test
- public void testRecentlyCommittedRollbackPersistence() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- Uninstall.packages(TestApp.A);
- Install.single(TestApp.A1).commit();
- Install.single(TestApp.A2).setEnableRollback().commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
- // The app should now be available for rollback.
- RollbackInfo available = waitForAvailableRollback(TestApp.A);
- assertThat(available).isNotNull();
-
- // Roll back the app.
- TestApp cause = new TestApp("Foo", "com.android.tests.rollback.testapp.Foo",
- /*versionCode*/ 42, /*isApex*/ false);
- RollbackUtils.rollback(available.getRollbackId(), cause);
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
- // Verify the recent rollback has been recorded.
- RollbackInfo committed = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
- assertThat(committed).isNotNull();
- assertThat(committed).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1));
- assertThat(committed).causePackagesContainsExactly(cause);
-
- // Reload the persisted data.
- rm.reloadPersistedData();
-
- // Verify the recent rollback is still recorded.
- committed = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
- assertThat(committed).isNotNull();
- assertThat(committed).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1));
- assertThat(committed).causePackagesContainsExactly(cause);
- assertThat(committed).hasRollbackId(available.getRollbackId());
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
* Test the scheduling aspect of rollback expiration.
*/
@Test
@@ -739,203 +550,6 @@
}
}
- /**
- * Test that the MANAGE_ROLLBACKS permission is required to call
- * RollbackManager APIs.
- */
- @Test
- public void testManageRollbacksPermission() throws Exception {
- // We shouldn't be allowed to call any of the RollbackManager APIs
- // without the MANAGE_ROLLBACKS permission.
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- try {
- rm.getAvailableRollbacks();
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
-
- try {
- rm.getRecentlyCommittedRollbacks();
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
-
- try {
- // TODO: What if the implementation checks arguments for non-null
- // first? Then this test isn't valid.
- rm.commitRollback(0, Collections.emptyList(), null);
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
-
- try {
- rm.reloadPersistedData();
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
-
- try {
- rm.expireRollbackForPackage(TestApp.A);
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
- }
-
- /**
- * Test that you cannot enable rollback for a package without the
- * MANAGE_ROLLBACKS permission.
- */
- @Test
- public void testEnableRollbackPermission() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES);
-
- Uninstall.packages(TestApp.A);
- Install.single(TestApp.A1).commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
- Install.single(TestApp.A2).setEnableRollback().commit();
-
- // We expect v2 of the app was installed, but rollback has not
- // been enabled.
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
- RollbackManager rm = RollbackUtils.getRollbackManager();
- assertThat(
- getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull();
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test that you cannot enable rollback for a non-module package when
- * holding the MANAGE_ROLLBACKS permission.
- */
- @Test
- public void testNonModuleEnableRollback() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.MANAGE_ROLLBACKS);
-
- Uninstall.packages(TestApp.A);
- Install.single(TestApp.A1).commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
- Install.single(TestApp.A2).setEnableRollback().commit();
-
- // We expect v2 of the app was installed, but rollback has not
- // been enabled because the test app is not a module.
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
- RollbackManager rm = RollbackUtils.getRollbackManager();
- assertThat(
- getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull();
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test rollback of multi-package installs is implemented.
- */
- @Test
- public void testMultiPackage() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- // Prep installation of the test apps.
- Uninstall.packages(TestApp.A, TestApp.B);
- Install.multi(TestApp.A1, TestApp.B1).commit();
- processUserData(TestApp.A);
- processUserData(TestApp.B);
- Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
- processUserData(TestApp.A);
- processUserData(TestApp.B);
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
- // TestApp.A should now be available for rollback.
- RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
- assertThat(rollback).isNotNull();
- assertThat(rollback).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Rollback the app. It should cause both test apps to be rolled
- // back.
- RollbackUtils.rollback(rollback.getRollbackId());
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-
- // We should see recent rollbacks listed for both A and B.
- Thread.sleep(1000);
- RollbackInfo rollbackA = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
-
- RollbackInfo rollbackB = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.B);
- assertThat(rollback).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- assertThat(rollbackA).hasRollbackId(rollbackB.getRollbackId());
-
- processUserData(TestApp.A);
- processUserData(TestApp.B);
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test failure to enable rollback for multi-package installs.
- * If any one of the packages fail to enable rollback, we shouldn't enable
- * rollback for any package.
- */
- @Test
- public void testMultiPackageEnableFail() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- Uninstall.packages(TestApp.A, TestApp.B);
- Install.single(TestApp.A1).commit();
- // We should fail to enable rollback here because TestApp B is not
- // already installed.
- Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
-
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
- assertThat(getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TestApp.A)).isNull();
- assertThat(getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TestApp.B)).isNull();
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
@Test
@Ignore("b/120200473")
/**