Merge "Initial file-based encryption public APIs."
diff --git a/core/java/android/security/net/config/ApplicationConfig.java b/core/java/android/security/net/config/ApplicationConfig.java
index c675352..9bf344a 100644
--- a/core/java/android/security/net/config/ApplicationConfig.java
+++ b/core/java/android/security/net/config/ApplicationConfig.java
@@ -48,7 +48,7 @@
*/
public boolean hasPerDomainConfigs() {
ensureInitialized();
- return mConfigs == null || !mConfigs.isEmpty();
+ return mConfigs != null && !mConfigs.isEmpty();
}
/**
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index 915fbef..0a4ce11 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -17,6 +17,9 @@
package android.security.net.config;
import android.util.ArraySet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -26,6 +29,12 @@
* @hide
*/
public final class NetworkSecurityConfig {
+ /** @hide */
+ public static final boolean DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED = true;
+ /** @hide */
+ public static final boolean DEFAULT_HSTS_ENFORCED = false;
+ public static final NetworkSecurityConfig DEFAULT = getDefaultBuilder().build();
+
private final boolean mCleartextTrafficPermitted;
private final boolean mHstsEnforced;
private final PinSet mPins;
@@ -35,7 +44,7 @@
private X509TrustManager mTrustManager;
private final Object mTrustManagerLock = new Object();
- public NetworkSecurityConfig(boolean cleartextTrafficPermitted, boolean hstsEnforced,
+ private NetworkSecurityConfig(boolean cleartextTrafficPermitted, boolean hstsEnforced,
PinSet pins, List<CertificatesEntryRef> certificatesEntryRefs) {
mCleartextTrafficPermitted = cleartextTrafficPermitted;
mHstsEnforced = hstsEnforced;
@@ -83,4 +92,151 @@
mAnchors = null;
}
}
+
+ /**
+ * Return a {@link Builder} for the default {@code NetworkSecurityConfig}.
+ *
+ * <p>
+ * The default configuration has the following properties:
+ * <ol>
+ * <li>Cleartext traffic is permitted.</li>
+ * <li>HSTS is not enforced.</li>
+ * <li>No certificate pinning is used.</li>
+ * <li>The system and user added trusted certificate stores are trusted for connections.</li>
+ * </ol>
+ *
+ * @hide
+ */
+ public static final Builder getDefaultBuilder() {
+ return new Builder()
+ .setCleartextTrafficPermitted(DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED)
+ .setHstsEnforced(DEFAULT_HSTS_ENFORCED)
+ // System certificate store, does not bypass static pins.
+ .addCertificatesEntryRef(
+ new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ // User certificate store, does not bypass static pins.
+ .addCertificatesEntryRef(
+ new CertificatesEntryRef(UserCertificateSource.getInstance(), false));
+ }
+
+ /**
+ * Builder for creating {@code NetworkSecurityConfig} objects.
+ * @hide
+ */
+ public static final class Builder {
+ private List<CertificatesEntryRef> mCertificatesEntryRefs;
+ private PinSet mPinSet;
+ private boolean mCleartextTrafficPermitted = DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED;
+ private boolean mHstsEnforced = DEFAULT_HSTS_ENFORCED;
+ private boolean mCleartextTrafficPermittedSet = false;
+ private boolean mHstsEnforcedSet = false;
+ private Builder mParentBuilder;
+
+ /**
+ * Sets the parent {@code Builder} for this {@code Builder}.
+ * The parent will be used to determine values not configured in this {@code Builder}
+ * in {@link Builder#build()}, recursively if needed.
+ */
+ public Builder setParent(Builder parent) {
+ // Sanity check to avoid adding loops.
+ Builder current = parent;
+ while (current != null) {
+ if (current == this) {
+ throw new IllegalArgumentException("Loops are not allowed in Builder parents");
+ }
+ current = current.getParent();
+ }
+ mParentBuilder = parent;
+ return this;
+ }
+
+ public Builder getParent() {
+ return mParentBuilder;
+ }
+
+ public Builder setPinSet(PinSet pinSet) {
+ mPinSet = pinSet;
+ return this;
+ }
+
+ private PinSet getEffectivePinSet() {
+ if (mPinSet != null) {
+ return mPinSet;
+ }
+ if (mParentBuilder != null) {
+ return mParentBuilder.getEffectivePinSet();
+ }
+ return PinSet.EMPTY_PINSET;
+ }
+
+ public Builder setCleartextTrafficPermitted(boolean cleartextTrafficPermitted) {
+ mCleartextTrafficPermitted = cleartextTrafficPermitted;
+ mCleartextTrafficPermittedSet = true;
+ return this;
+ }
+
+ private boolean getEffectiveCleartextTrafficPermitted() {
+ if (mCleartextTrafficPermittedSet) {
+ return mCleartextTrafficPermitted;
+ }
+ if (mParentBuilder != null) {
+ return mParentBuilder.getEffectiveCleartextTrafficPermitted();
+ }
+ return DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED;
+ }
+
+ public Builder setHstsEnforced(boolean hstsEnforced) {
+ mHstsEnforced = hstsEnforced;
+ mHstsEnforcedSet = true;
+ return this;
+ }
+
+ private boolean getEffectiveHstsEnforced() {
+ if (mHstsEnforcedSet) {
+ return mHstsEnforced;
+ }
+ if (mParentBuilder != null) {
+ return mParentBuilder.getEffectiveHstsEnforced();
+ }
+ return DEFAULT_HSTS_ENFORCED;
+ }
+
+ public Builder addCertificatesEntryRef(CertificatesEntryRef ref) {
+ if (mCertificatesEntryRefs == null) {
+ mCertificatesEntryRefs = new ArrayList<CertificatesEntryRef>();
+ }
+ mCertificatesEntryRefs.add(ref);
+ return this;
+ }
+
+ public Builder addCertificatesEntryRefs(Collection<? extends CertificatesEntryRef> refs) {
+ if (mCertificatesEntryRefs == null) {
+ mCertificatesEntryRefs = new ArrayList<CertificatesEntryRef>();
+ }
+ mCertificatesEntryRefs.addAll(refs);
+ return this;
+ }
+
+ private List<CertificatesEntryRef> getEffectiveCertificatesEntryRefs() {
+ if (mCertificatesEntryRefs != null) {
+ return mCertificatesEntryRefs;
+ }
+ if (mParentBuilder != null) {
+ return mParentBuilder.getEffectiveCertificatesEntryRefs();
+ }
+ return Collections.<CertificatesEntryRef>emptyList();
+ }
+
+ public boolean hasCertificateEntryRefs() {
+ return mCertificatesEntryRefs != null;
+ }
+
+ public NetworkSecurityConfig build() {
+ boolean cleartextPermitted = getEffectiveCleartextTrafficPermitted();
+ boolean hstsEnforced = getEffectiveCleartextTrafficPermitted();
+ PinSet pinSet = getEffectivePinSet();
+ List<CertificatesEntryRef> entryRefs = getEffectiveCertificatesEntryRefs();
+ return new NetworkSecurityConfig(cleartextPermitted, hstsEnforced, pinSet, entryRefs);
+ }
+ }
}
diff --git a/core/java/android/security/net/config/PinSet.java b/core/java/android/security/net/config/PinSet.java
index a9ee039..d3c975e 100644
--- a/core/java/android/security/net/config/PinSet.java
+++ b/core/java/android/security/net/config/PinSet.java
@@ -17,10 +17,13 @@
package android.security.net.config;
import android.util.ArraySet;
+import java.util.Collections;
import java.util.Set;
/** @hide */
public final class PinSet {
+ public static final PinSet EMPTY_PINSET =
+ new PinSet(Collections.<Pin>emptySet(), Long.MAX_VALUE);
public final long expirationTime;
public final Set<Pin> pins;
diff --git a/core/java/android/security/net/config/SystemCertificateSource.java b/core/java/android/security/net/config/SystemCertificateSource.java
index 640ebd9..7649a97 100644
--- a/core/java/android/security/net/config/SystemCertificateSource.java
+++ b/core/java/android/security/net/config/SystemCertificateSource.java
@@ -36,18 +36,23 @@
* @hide
*/
public class SystemCertificateSource implements CertificateSource {
- private static Set<X509Certificate> sSystemCerts = null;
- private static final Object sLock = new Object();
+ private static final SystemCertificateSource INSTANCE = new SystemCertificateSource();
+ private Set<X509Certificate> mSystemCerts = null;
+ private final Object mLock = new Object();
- public SystemCertificateSource() {
+ private SystemCertificateSource() {
+ }
+
+ public static SystemCertificateSource getInstance() {
+ return INSTANCE;
}
@Override
public Set<X509Certificate> getCertificates() {
// TODO: loading all of these is wasteful, we should instead use a keystore style API.
- synchronized (sLock) {
- if (sSystemCerts != null) {
- return sSystemCerts;
+ synchronized (mLock) {
+ if (mSystemCerts != null) {
+ return mSystemCerts;
}
CertificateFactory certFactory;
try {
@@ -83,14 +88,14 @@
IoUtils.closeQuietly(is);
}
}
- sSystemCerts = systemCerts;
- return sSystemCerts;
+ mSystemCerts = systemCerts;
+ return mSystemCerts;
}
}
public void onCertificateStorageChange() {
- synchronized (sLock) {
- sSystemCerts = null;
+ synchronized (mLock) {
+ mSystemCerts = null;
}
}
}
diff --git a/core/java/android/security/net/config/UserCertificateSource.java b/core/java/android/security/net/config/UserCertificateSource.java
index 77e2c88..e9d5aa1 100644
--- a/core/java/android/security/net/config/UserCertificateSource.java
+++ b/core/java/android/security/net/config/UserCertificateSource.java
@@ -36,18 +36,23 @@
* @hide
*/
public class UserCertificateSource implements CertificateSource {
- private static Set<X509Certificate> sUserCerts = null;
- private static final Object sLock = new Object();
+ private static final UserCertificateSource INSTANCE = new UserCertificateSource();
+ private Set<X509Certificate> mUserCerts = null;
+ private final Object mLock = new Object();
- public UserCertificateSource() {
+ private UserCertificateSource() {
+ }
+
+ public static UserCertificateSource getInstance() {
+ return INSTANCE;
}
@Override
public Set<X509Certificate> getCertificates() {
// TODO: loading all of these is wasteful, we should instead use a keystore style API.
- synchronized (sLock) {
- if (sUserCerts != null) {
- return sUserCerts;
+ synchronized (mLock) {
+ if (mUserCerts != null) {
+ return mUserCerts;
}
CertificateFactory certFactory;
try {
@@ -57,32 +62,31 @@
}
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
final File userCaDir = new File(configDir, "cacerts-added");
- if (!userCaDir.isDirectory()) {
- throw new AssertionError(userCaDir + " is not a directory");
- }
-
Set<X509Certificate> userCerts = new ArraySet<X509Certificate>();
- for (String caFile : userCaDir.list()) {
- InputStream is = null;
- try {
- is = new BufferedInputStream(
- new FileInputStream(new File(userCaDir, caFile)));
- userCerts.add((X509Certificate) certFactory.generateCertificate(is));
- } catch (CertificateException | IOException e) {
- // Don't rethrow to be consistent with conscrypt's cert loading code.
- continue;
- } finally {
- IoUtils.closeQuietly(is);
+ // If the user hasn't added any certificates the directory may not exist.
+ if (userCaDir.isDirectory()) {
+ for (String caFile : userCaDir.list()) {
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(
+ new FileInputStream(new File(userCaDir, caFile)));
+ userCerts.add((X509Certificate) certFactory.generateCertificate(is));
+ } catch (CertificateException | IOException e) {
+ // Don't rethrow to be consistent with conscrypt's cert loading code.
+ continue;
+ } finally {
+ IoUtils.closeQuietly(is);
+ }
}
}
- sUserCerts = userCerts;
- return sUserCerts;
+ mUserCerts = userCerts;
+ return mUserCerts;
}
}
public void onCertificateStorageChange() {
- synchronized (sLock) {
- sUserCerts = null;
+ synchronized (mLock) {
+ mUserCerts = null;
}
}
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 28b22bf7..7b5f5ab 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -219,6 +219,11 @@
*/
void cancelTaskWindowTransition(int taskId);
+ /**
+ * Cancels the thumbnail transitions for the given task.
+ */
+ void cancelTaskThumbnailTransition(int taskId);
+
// These can only be called with the SET_ORIENTATION permission.
/**
* Update the current screen rotation based on the current state of
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 10d862e..d05c66a 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -144,7 +144,7 @@
mAlpha = alpha;
if (mCurrDrawable != null) {
if (mEnterAnimationEnd == 0) {
- mCurrDrawable.mutate().setAlpha(alpha);
+ mCurrDrawable.setAlpha(alpha);
} else {
animate(false);
}
@@ -162,7 +162,7 @@
if (mDrawableContainerState.mDither != dither) {
mDrawableContainerState.mDither = dither;
if (mCurrDrawable != null) {
- mCurrDrawable.mutate().setDither(mDrawableContainerState.mDither);
+ mCurrDrawable.setDither(mDrawableContainerState.mDither);
}
}
}
@@ -175,7 +175,7 @@
mDrawableContainerState.mColorFilter = colorFilter;
if (mCurrDrawable != null) {
- mCurrDrawable.mutate().setColorFilter(colorFilter);
+ mCurrDrawable.setColorFilter(colorFilter);
}
}
}
@@ -188,7 +188,7 @@
mDrawableContainerState.mTintList = tint;
if (mCurrDrawable != null) {
- mCurrDrawable.mutate().setTintList(tint);
+ mCurrDrawable.setTintList(tint);
}
}
}
@@ -201,7 +201,7 @@
mDrawableContainerState.mTintMode = tintMode;
if (mCurrDrawable != null) {
- mCurrDrawable.mutate().setTintMode(tintMode);
+ mCurrDrawable.setTintMode(tintMode);
}
}
}
@@ -244,7 +244,7 @@
if (mDrawableContainerState.mAutoMirrored != mirrored) {
mDrawableContainerState.mAutoMirrored = mirrored;
if (mCurrDrawable != null) {
- mCurrDrawable.mutate().setAutoMirrored(mDrawableContainerState.mAutoMirrored);
+ mCurrDrawable.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
}
}
}
@@ -266,7 +266,7 @@
if (mCurrDrawable != null) {
mCurrDrawable.jumpToCurrentState();
if (mHasAlpha) {
- mCurrDrawable.mutate().setAlpha(mAlpha);
+ mCurrDrawable.setAlpha(mAlpha);
}
}
if (mExitAnimationEnd != 0) {
@@ -499,8 +499,6 @@
* @param d The drawable to initialize.
*/
private void initializeDrawableForDisplay(Drawable d) {
- d.mutate();
-
if (mDrawableContainerState.mEnterFadeDuration <= 0 && mHasAlpha) {
d.setAlpha(mAlpha);
}
@@ -540,13 +538,12 @@
if (mCurrDrawable != null) {
if (mEnterAnimationEnd != 0) {
if (mEnterAnimationEnd <= now) {
- mCurrDrawable.mutate().setAlpha(mAlpha);
+ mCurrDrawable.setAlpha(mAlpha);
mEnterAnimationEnd = 0;
} else {
int animAlpha = (int)((mEnterAnimationEnd-now)*255)
/ mDrawableContainerState.mEnterFadeDuration;
- if (DEBUG) android.util.Log.i(TAG, toString() + " cur alpha " + animAlpha);
- mCurrDrawable.mutate().setAlpha(((255-animAlpha)*mAlpha)/255);
+ mCurrDrawable.setAlpha(((255-animAlpha)*mAlpha)/255);
animating = true;
}
}
@@ -563,8 +560,7 @@
} else {
int animAlpha = (int)((mExitAnimationEnd-now)*255)
/ mDrawableContainerState.mExitFadeDuration;
- if (DEBUG) android.util.Log.i(TAG, toString() + " last alpha " + animAlpha);
- mLastDrawable.mutate().setAlpha((animAlpha*mAlpha)/255);
+ mLastDrawable.setAlpha((animAlpha*mAlpha)/255);
animating = true;
}
}
@@ -832,9 +828,7 @@
private Drawable prepareDrawable(Drawable child) {
child.setLayoutDirection(mLayoutDirection);
child.setCallback(mOwner);
- if (mMutated) {
- child = child.mutate();
- }
+ child = child.mutate();
return child;
}
diff --git a/libs/androidfw/tests/AppAsLib_test.cpp b/libs/androidfw/tests/AppAsLib_test.cpp
index bdb0c3d..8489acf 100644
--- a/libs/androidfw/tests/AppAsLib_test.cpp
+++ b/libs/androidfw/tests/AppAsLib_test.cpp
@@ -16,7 +16,6 @@
#include <androidfw/ResourceTypes.h>
-#include "data/basic/R.h"
#include "data/appaslib/R.h"
#include <gtest/gtest.h>
@@ -25,29 +24,45 @@
namespace {
-#include "data/basic/basic_arsc.h"
+#include "data/appaslib/appaslib_arsc.h"
+#include "data/appaslib/appaslib_lib_arsc.h"
+// This tests the app resources loaded as app.
TEST(AppAsLibTest, loadedAsApp) {
ResTable table;
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+ ASSERT_EQ(NO_ERROR, table.add(appaslib_arsc, appaslib_arsc_len));
Res_value val;
- ssize_t block = table.getResource(base::R::integer::number2, &val);
+ ssize_t block = table.getResource(appaslib::R::app::integer::number1, &val);
ASSERT_GE(block, 0);
ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(base::R::array::integerArray1, val.data);
+ ASSERT_EQ(appaslib::R::app::array::integerArray1, val.data);
}
+// This tests the app resources loaded as shared-lib.
TEST(AppAsLibTest, loadedAsSharedLib) {
ResTable table;
// Load as shared library.
- ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len, NULL, 0, -1, false, true));
+ ASSERT_EQ(NO_ERROR, table.add(appaslib_arsc, appaslib_arsc_len, NULL, 0, -1, false, true));
Res_value val;
- ssize_t block = table.getResource(appaslib::R::integer::number2, &val);
+ ssize_t block = table.getResource(appaslib::R::lib::integer::number1, &val);
ASSERT_GE(block, 0);
ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
- ASSERT_EQ(appaslib::R::array::integerArray1, val.data);
+ ASSERT_EQ(appaslib::R::lib::array::integerArray1, val.data);
+}
+
+// This tests the shared-lib loaded with appAsLib as true.
+TEST(AppAsLibTest, loadedSharedLib) {
+ ResTable table;
+ // Load shared library with appAsLib as true.
+ ASSERT_EQ(NO_ERROR, table.add(appaslib_lib_arsc, appaslib_lib_arsc_len, NULL, 0, -1, false, true));
+
+ Res_value val;
+ ssize_t block = table.getResource(appaslib::R::lib::integer::number1, &val);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType);
+ ASSERT_EQ(appaslib::R::lib::array::integerArray1, val.data);
}
}
diff --git a/libs/androidfw/tests/data/appaslib/AndroidManifest.xml b/libs/androidfw/tests/data/appaslib/AndroidManifest.xml
new file mode 100644
index 0000000..e00045b
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.test.basic">
+ <application>
+ </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/appaslib/R.h b/libs/androidfw/tests/data/appaslib/R.h
index f89d4bf..3af921a 100644
--- a/libs/androidfw/tests/data/appaslib/R.h
+++ b/libs/androidfw/tests/data/appaslib/R.h
@@ -19,19 +19,33 @@
namespace appaslib {
namespace R {
-
+namespace lib {
namespace integer {
enum {
- number2 = 0x02040001, // default
+ number1 = 0x02020000, // default
};
}
namespace array {
enum {
- integerArray1 = 0x02060000, // default
+ integerArray1 = 0x02030000, // default
+ };
+}
+} // namespace lib
+
+namespace app {
+namespace integer {
+ enum {
+ number1 = 0x7f020000, // default
};
}
+namespace array {
+ enum {
+ integerArray1 = 0x7f030000, // default
+ };
+}
+} // namespace app
} // namespace R
} // namespace appaslib
diff --git a/libs/androidfw/tests/data/appaslib/appaslib_arsc.h b/libs/androidfw/tests/data/appaslib/appaslib_arsc.h
new file mode 100644
index 0000000..be176ab
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/appaslib_arsc.h
@@ -0,0 +1,68 @@
+unsigned char appaslib_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0x04, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xdc, 0x02, 0x00, 0x00,
+ 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
+ 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00,
+ 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0d, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00,
+ 0x72, 0x00, 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x7f,
+ 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
+ 0x03, 0x00, 0x00, 0x00
+};
+unsigned int appaslib_arsc_len = 772;
diff --git a/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h b/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h
new file mode 100644
index 0000000..099285a
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/appaslib_lib_arsc.h
@@ -0,0 +1,68 @@
+unsigned char appaslib_lib_arsc[] = {
+ 0x02, 0x00, 0x0c, 0x00, 0x04, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xdc, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
+ 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
+ 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
+ 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
+ 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00,
+ 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x54, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
+ 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0d, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00,
+ 0x72, 0x00, 0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00,
+ 0x31, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x00,
+ 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
+ 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
+ 0x03, 0x00, 0x00, 0x00
+};
+unsigned int appaslib_lib_arsc_len = 772;
diff --git a/libs/androidfw/tests/data/appaslib/build b/libs/androidfw/tests/data/appaslib/build
new file mode 100755
index 0000000..e4bd88b
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/build
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# Copyright (C) 2015 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.
+#
+
+PATH_TO_FRAMEWORK_RES=$(gettop)/prebuilts/sdk/current/android.jar
+
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F bundle.apk -f && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc appaslib.arsc && \
+xxd -i appaslib.arsc > appaslib_arsc.h && \
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES -F bundle.apk -f --shared-lib && \
+unzip bundle.apk resources.arsc && \
+mv resources.arsc appaslib_lib.arsc && \
+xxd -i appaslib_lib.arsc > appaslib_lib_arsc.h \
+
diff --git a/libs/androidfw/tests/data/appaslib/res/values/values.xml b/libs/androidfw/tests/data/appaslib/res/values/values.xml
new file mode 100644
index 0000000..39b99a6
--- /dev/null
+++ b/libs/androidfw/tests/data/appaslib/res/values/values.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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>
+ <integer name="number1">@array/integerArray1</integer>
+ <integer-array name="integerArray1">
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </integer-array>
+</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 57ee319..3d78028 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -603,6 +603,7 @@
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (DEBUG) Log.d(TAG, "received broadcast " + action);
@@ -656,6 +657,7 @@
private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
+ @Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
@@ -788,6 +790,7 @@
return new SimData(state, slotId, subId);
}
+ @Override
public String toString() {
return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}";
}
@@ -1693,5 +1696,19 @@
for (int subId : mServiceStates.keySet()) {
pw.println(" " + subId + "=" + mServiceStates.get(subId));
}
+ if (mFpm != null && mFpm.isHardwareDetected()) {
+ final int userId = ActivityManager.getCurrentUser();
+ final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
+ pw.println(" Fingerprint state (user=" + userId + ")");
+ pw.println(" allowed=" + isUnlockingWithFingerprintAllowed());
+ pw.println(" auth'd=" + mUserFingerprintAuthenticated.get(userId));
+ pw.println(" authSinceBoot="
+ + getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
+ pw.println(" disabled(DPM)=" + isFingerprintDisabled(userId));
+ pw.println(" possible=" + isUnlockWithFingerprintPossible(userId));
+ pw.println(" strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
+ pw.println(" timedout=" + hasFingerprintUnlockTimedOut(userId));
+ pw.println(" trustManaged=" + getUserTrustIsManaged(userId));
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index ebfacac..a429447 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -21,6 +21,7 @@
*/
public class Constants {
+ // TODO: Move into RecentsMetrics
public static class Metrics {
// DO NOT MODIFY THE ORDER OF THESE METRICS
public static final int DismissSourceKeyboard = 0;
@@ -28,6 +29,7 @@
public static final int DismissSourceHeaderButton = 2;
}
+ // TODO: Move into RecentsDebugFlags
public static class DebugFlags {
public static class App {
@@ -37,7 +39,7 @@
public static final boolean EnableTaskFiltering = false;
// Enables dismiss-all
public static final boolean EnableDismissAll = false;
- // Enables fast-toggling
+ // Enables fast-toggling by just tapping on the recents button
public static final boolean EnableFastToggleRecents = false;
// Enables the thumbnail alpha on the front-most task
public static final boolean EnableThumbnailAlphaOnFrontmost = false;
@@ -57,14 +59,4 @@
public static final int SystemServicesProxyMockTaskCount = 100;
}
}
-
- public static class Values {
- public static class App {
- public static int AppWidgetHostId = 1024;
- }
-
- public static class TaskStackView {
- public static final int FilterStartDelay = 25;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f800785..6874247 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -32,19 +32,20 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
-
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
+import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationStartedEvent;
+import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
-import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
@@ -57,7 +58,6 @@
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
-import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -137,8 +137,7 @@
try {
startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(), UserHandle.CURRENT);
} catch (Exception e) {
- Console.logError(RecentsActivity.this,
- getString(R.string.recents_launch_error_message, "Home"));
+ Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
}
}
}
@@ -345,7 +344,7 @@
// Initialize the widget host (the host id is static and does not change)
if (!Constants.DebugFlags.App.DisableSearchBar) {
- mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
+ mAppWidgetHost = new RecentsAppWidgetHost(this, RecentsAppWidgetHost.HOST_ID);
}
mPackageMonitor = new RecentsPackageMonitor();
mPackageMonitor.register(this);
@@ -511,12 +510,7 @@
if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
// As we iterate to the next/previous task, cancel any current/lagging window
// transition animations
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- if (launchState.launchedToTaskId != -1) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.cancelWindowTransition(launchState.launchedToTaskId);
- }
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
// Focus the next task in the stack
final boolean backward = event.isShiftPressed();
@@ -575,10 +569,6 @@
/**** RecentsView.RecentsViewCallbacks Implementation ****/
@Override
- public void onTaskViewClicked() {
- }
-
- @Override
public void onTaskLaunchFailed() {
// Return to Home
dismissRecentsToHome(true);
@@ -657,6 +647,17 @@
mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
}
+ public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
+ RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+ int launchToTaskId = launchState.launchedToTaskId;
+ if (launchToTaskId != -1 &&
+ (event.launchTask == null || launchToTaskId != event.launchTask.key.id)) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ssp.cancelWindowTransition(launchState.launchedToTaskId);
+ ssp.cancelThumbnailTransition(getTaskId());
+ }
+ }
+
public final void onBusEvent(AppWidgetProviderChangedEvent event) {
refreshSearchWidgetView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index 9ee6f5b..01ffd2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -19,7 +19,6 @@
/**
* The launch state of the RecentsActivity.
*
- * TODO: We will be refactoring this out RecentsConfiguration.
* Current Constraints:
* - needed in onStart() before onNewIntent()
* - needs to be reset when Recents is hidden
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
index fc96c11..573db98 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
@@ -26,6 +26,8 @@
/** Our special app widget host for the Search widget */
public class RecentsAppWidgetHost extends AppWidgetHost {
+ public static final int HOST_ID = 1024;
+
boolean mIsListening;
public RecentsAppWidgetHost(Context context, int hostId) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 675ef2f..db65e00 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -16,8 +16,6 @@
package com.android.systemui.recents;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ITaskStackListener;
@@ -32,24 +30,24 @@
import android.os.Handler;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.util.Log;
import android.util.MutableBoolean;
import android.view.AppTransitionAnimationSpec;
import android.view.LayoutInflater;
import android.view.View;
-
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationStartedEvent;
+import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
-import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
-import com.android.systemui.recents.misc.Console;
+import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ForegroundThread;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
@@ -57,14 +55,16 @@
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.views.TaskStackView;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
+import com.android.systemui.recents.views.TaskStackView;
import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import java.util.ArrayList;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+
/**
* An implementation of the Recents component for the current user. For secondary users, this can
* be called remotely from the system user.
@@ -75,7 +75,12 @@
private final static String TAG = "RecentsImpl";
private final static boolean DEBUG = false;
- private final static int sMinToggleDelay = 350;
+ // The minimum amount of time between each recents button press that we will handle
+ private final static int MIN_TOGGLE_DELAY_MS = 350;
+ // The duration within which the user releasing the alt tab (from when they pressed alt tab)
+ // that the fast alt-tab animation will run. If the user's alt-tab takes longer than this
+ // duration, then we will toggle recents after this duration.
+ private final static int FAST_ALT_TAB_DELAY_MS = 225;
public final static String RECENTS_PACKAGE = "com.android.systemui";
public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
@@ -156,6 +161,14 @@
// Variables to keep track of if we need to start recents after binding
boolean mTriggeredFromAltTab;
long mLastToggleTime;
+ DozeTrigger mFastAltTabTrigger = new DozeTrigger(FAST_ALT_TAB_DELAY_MS, new Runnable() {
+ @Override
+ public void run() {
+ // When this fires, then the user has not released alt-tab for at least
+ // FAST_ALT_TAB_DELAY_MS milliseconds
+ showRecents(mTriggeredFromAltTab);
+ }
+ });
Bitmap mThumbnailTransitionBitmapCache;
Task mThumbnailTransitionBitmapCacheKey;
@@ -164,7 +177,7 @@
public RecentsImpl(Context context) {
mContext = context;
mHandler = new Handler();
- mAppWidgetHost = new RecentsAppWidgetHost(mContext, Constants.Values.App.AppWidgetHostId);
+ mAppWidgetHost = new RecentsAppWidgetHost(mContext, RecentsAppWidgetHost.HOST_ID);
Resources res = mContext.getResources();
LayoutInflater inflater = LayoutInflater.from(mContext);
@@ -239,6 +252,29 @@
@Override
public void showRecents(boolean triggeredFromAltTab) {
mTriggeredFromAltTab = triggeredFromAltTab;
+ if (mFastAltTabTrigger.hasTriggered()) {
+ // We are calling this from the doze trigger, so just fall through to show Recents
+ mFastAltTabTrigger.resetTrigger();
+ } else if (mFastAltTabTrigger.isDozing()) {
+ // We are dozing but haven't yet triggered, ignore this if this is not another alt-tab,
+ // otherwise, this is an additional tab (alt-tab*), which means that we should trigger
+ // immediately (fall through and disable the pending trigger)
+ // TODO: This is tricky, we need to handle the tab key, but Recents has not yet started
+ // so we may actually additional signal to handle multiple quick tab cases. The
+ // severity of this is inversely proportional to the FAST_ALT_TAB_DELAY_MS
+ // duration though
+ if (!triggeredFromAltTab) {
+ return;
+ }
+ mFastAltTabTrigger.stopDozing();
+ } else {
+ // Otherwise, the doze trigger is not running, and if this is an alt tab, we should
+ // start the trigger and then wait for the hide (or for it to elapse)
+ if (triggeredFromAltTab) {
+ mFastAltTabTrigger.startDozing();
+ return;
+ }
+ }
try {
// Check if the top task is in the home stack, and start the recents activity
@@ -249,13 +285,24 @@
startRecentsActivity(topTask, isTopTaskHome.value);
}
} catch (ActivityNotFoundException e) {
- Console.logRawError("Failed to launch RecentAppsIntent", e);
+ Log.e(TAG, "Failed to launch RecentsActivity", e);
}
}
@Override
public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
if (mBootCompleted) {
+ if (triggeredFromAltTab && mFastAltTabTrigger.isDozing()) {
+ // The user has released alt-tab before the trigger has run, so just show the next
+ // task immediately
+ showNextTask();
+
+ // Cancel the fast alt-tab trigger
+ mFastAltTabTrigger.stopDozing();
+ mFastAltTabTrigger.resetTrigger();
+ return;
+ }
+
// Defer to the activity to handle hiding recents, if it handles it, then it must still
// be visible
EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab,
@@ -265,6 +312,11 @@
@Override
public void toggleRecents() {
+ // Skip this toggle if we are already waiting to trigger recents via alt-tab
+ if (mFastAltTabTrigger.isDozing()) {
+ return;
+ }
+
mTriggeredFromAltTab = false;
try {
@@ -283,7 +335,7 @@
// better than showing a janky screenshot).
// NOTE: Ideally, the screenshot mechanism would take the window transform into
// account
- if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
+ if ((SystemClock.elapsedRealtime() - mLastToggleTime) < MIN_TOGGLE_DELAY_MS) {
return;
}
@@ -296,7 +348,7 @@
// better than showing a janky screenshot).
// NOTE: Ideally, the screenshot mechanism would take the window transform into
// account
- if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
+ if ((SystemClock.elapsedRealtime() - mLastToggleTime) < MIN_TOGGLE_DELAY_MS) {
return;
}
@@ -305,7 +357,7 @@
mLastToggleTime = SystemClock.elapsedRealtime();
}
} catch (ActivityNotFoundException e) {
- Console.logRawError("Failed to launch RecentAppsIntent", e);
+ Log.e(TAG, "Failed to launch RecentsActivity", e);
}
}
@@ -335,10 +387,58 @@
// Do nothing
}
- public void showRelativeAffiliatedTask(boolean showNextTask) {
- // Return early if there is no focused stack
+ /**
+ * Transitions to the next recent task in the stack.
+ */
+ public void showNextTask() {
SystemServicesProxy ssp = Recents.getSystemServices();
- int focusedStackId = ssp.getFocusedStack();
+ RecentsTaskLoader loader = Recents.getTaskLoader();
+ RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
+ loader.preloadTasks(plan, true /* isTopTaskHome */);
+ TaskStack focusedStack = plan.getTaskStack();
+
+ // Return early if there are no tasks in the focused stack
+ if (focusedStack == null || focusedStack.getTaskCount() == 0) return;
+
+ ActivityManager.RunningTaskInfo runningTask = ssp.getTopMostTask();
+ // Return early if there is no running task
+ if (runningTask == null) return;
+ // Return early if the running task is in the home stack (optimization)
+ if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return;
+
+ // Find the task in the recents list
+ ArrayList<Task> tasks = focusedStack.getTasks();
+ Task toTask = null;
+ ActivityOptions launchOpts = null;
+ int taskCount = tasks.size();
+ for (int i = taskCount - 1; i >= 1; i--) {
+ Task task = tasks.get(i);
+ if (task.key.id == runningTask.id) {
+ toTask = tasks.get(i - 1);
+ launchOpts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_prev_affiliated_task_target,
+ R.anim.recents_launch_prev_affiliated_task_source);
+ break;
+ }
+ }
+
+ // Return early if there is no next task
+ if (toTask == null) {
+ ssp.startInPlaceAnimationOnFrontMostApplication(
+ ActivityOptions.makeCustomInPlaceAnimation(mContext,
+ R.anim.recents_launch_prev_affiliated_task_bounce));
+ return;
+ }
+
+ // Launch the task
+ ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts);
+ }
+
+ /**
+ * Transitions to the next affiliated task.
+ */
+ public void showRelativeAffiliatedTask(boolean showNextTask) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
loader.preloadTasks(plan, true /* isTopTaskHome */);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java
new file mode 100644
index 0000000..7604de1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 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.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.Task;
+
+/**
+ * This is sent when we want to cancel the enter-recents window animation for the launch task.
+ */
+public class CancelEnterRecentsWindowAnimationEvent extends EventBus.Event {
+
+ // This is set for the task that is launching, which allows us to ensure that we are not
+ // cancelling the same task animation (it will just be overwritten instead)
+ public final Task launchTask;
+
+ public CancelEnterRecentsWindowAnimationEvent(Task launchTask) {
+ this.launchTask = launchTask;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Console.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Console.java
deleted file mode 100644
index 28ac9d3..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Console.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2014 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.recents.misc;
-
-
-import android.content.ComponentCallbacks2;
-import android.content.Context;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.widget.Toast;
-
-import java.util.HashMap;
-import java.util.Map;
-
-
-public class Console {
- // Timer
- public static final Map<Object, Long> mTimeLogs = new HashMap<Object, Long>();
-
- // Colors
- public static final String AnsiReset = "\u001B[0m";
- public static final String AnsiBlack = "\u001B[30m";
- public static final String AnsiRed = "\u001B[31m"; // SystemUIHandshake
- public static final String AnsiGreen = "\u001B[32m"; // MeasureAndLayout
- public static final String AnsiYellow = "\u001B[33m"; // SynchronizeViewsWithModel
- public static final String AnsiBlue = "\u001B[34m"; // TouchEvents, Search
- public static final String AnsiPurple = "\u001B[35m"; // Draw
- public static final String AnsiCyan = "\u001B[36m"; // ClickEvents
- public static final String AnsiWhite = "\u001B[37m";
-
- // Console enabled state
- public static boolean Enabled = false;
-
- /** Logs a key */
- public static void log(String key) {
- log(true, key, "", AnsiReset);
- }
-
- /** Logs a conditioned key */
- public static void log(boolean condition, String key) {
- if (condition) {
- log(condition, key, "", AnsiReset);
- }
- }
-
- /** Logs a key in a specific color */
- public static void log(boolean condition, String key, Object data) {
- if (condition) {
- log(condition, key, data, AnsiReset);
- }
- }
-
- /** Logs a key with data in a specific color */
- public static void log(boolean condition, String key, Object data, String color) {
- if (condition) {
- System.out.println(color + key + AnsiReset + " " + data.toString());
- }
- }
-
- /** Logs an error */
- public static void logError(Context context, String msg) {
- Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
- Log.e("Recents", msg);
- }
-
- /** Logs a raw error */
- public static void logRawError(String msg, Exception e) {
- Log.e("Recents", msg, e);
- }
-
- /** Logs a divider bar */
- public static void logDivider(boolean condition) {
- if (condition) {
- System.out.println("==== [" + System.currentTimeMillis() +
- "] ============================================================");
- }
- }
-
- /** Starts a time trace */
- public static void logStartTracingTime(boolean condition, String key) {
- if (condition) {
- long curTime = System.currentTimeMillis();
- mTimeLogs.put(key, curTime);
- Console.log(condition, "[Recents|" + key + "]",
- "started @ " + curTime);
- }
- }
-
- /** Continues a time trace */
- public static void logTraceTime(boolean condition, String key, String desc) {
- if (condition) {
- long timeDiff = System.currentTimeMillis() - mTimeLogs.get(key);
- Console.log(condition, "[Recents|" + key + "|" + desc + "]",
- "+" + timeDiff + "ms");
- }
- }
-
- /** Logs a stack trace */
- public static void logStackTrace() {
- logStackTrace("", 99);
- }
-
- /** Logs a stack trace to a certain depth */
- public static void logStackTrace(int depth) {
- logStackTrace("", depth);
- }
-
- /** Logs a stack trace to a certain depth with a key */
- public static void logStackTrace(String key, int depth) {
- int offset = 0;
- StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
- String tinyStackTrace = "";
- // Skip over the known stack trace classes
- for (int i = 0; i < callStack.length; i++) {
- StackTraceElement el = callStack[i];
- String className = el.getClassName();
- if (className.indexOf("dalvik.system.VMStack") == -1 &&
- className.indexOf("java.lang.Thread") == -1 &&
- className.indexOf("recents.Console") == -1) {
- break;
- } else {
- offset++;
- }
- }
- // Build the pretty stack trace
- int start = Math.min(offset + depth, callStack.length);
- int end = offset;
- String indent = "";
- for (int i = start - 1; i >= end; i--) {
- StackTraceElement el = callStack[i];
- tinyStackTrace += indent + " -> " + el.getClassName() +
- "[" + el.getLineNumber() + "]." + el.getMethodName();
- if (i > end) {
- tinyStackTrace += "\n";
- indent += " ";
- }
- }
- log(true, key, tinyStackTrace, AnsiRed);
- }
-
-
- /** Returns the stringified MotionEvent action */
- public static String motionEventActionToString(int action) {
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- return "Down";
- case MotionEvent.ACTION_UP:
- return "Up";
- case MotionEvent.ACTION_MOVE:
- return "Move";
- case MotionEvent.ACTION_CANCEL:
- return "Cancel";
- case MotionEvent.ACTION_POINTER_DOWN:
- return "Pointer Down";
- case MotionEvent.ACTION_POINTER_UP:
- return "Pointer Up";
- default:
- return "" + action;
- }
- }
-
- public static String trimMemoryLevelToString(int level) {
- switch (level) {
- case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
- return "UI Hidden";
- case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
- return "Running Moderate";
- case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
- return "Background";
- case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
- return "Running Low";
- case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
- return "Moderate";
- case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
- return "Critical";
- case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
- return "Complete";
- default:
- return "" + level;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
index 336d2db..dc8f547 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
@@ -29,44 +29,53 @@
boolean mIsDozing;
boolean mHasTriggered;
int mDozeDurationMilliseconds;
- Runnable mSleepRunnable;
+ Runnable mOnSleepRunnable;
// Sleep-runnable
Runnable mDozeRunnable = new Runnable() {
@Override
public void run() {
- mSleepRunnable.run();
mIsDozing = false;
mHasTriggered = true;
+ mOnSleepRunnable.run();
}
};
- public DozeTrigger(int dozeDurationMilliseconds, Runnable sleepRunnable) {
+ public DozeTrigger(int dozeDurationMilliseconds, Runnable onSleepRunnable) {
mHandler = new Handler();
mDozeDurationMilliseconds = dozeDurationMilliseconds;
- mSleepRunnable = sleepRunnable;
+ mOnSleepRunnable = onSleepRunnable;
}
- /** Starts dozing. This also resets the trigger flag. */
+ /**
+ * Starts dozing and queues the onSleepRunnable to be called. This also resets the trigger flag.
+ */
public void startDozing() {
forcePoke();
mHasTriggered = false;
}
- /** Stops dozing. */
+ /**
+ * Stops dozing and prevents the onSleepRunnable from being called.
+ */
public void stopDozing() {
mHandler.removeCallbacks(mDozeRunnable);
mIsDozing = false;
}
- /** Poke this dozer to wake it up for a little bit, if it is dozing. */
+ /**
+ * Poke this dozer to wake it up if it is dozing, delaying the onSleepRunnable from being
+ * called for a for the doze duration.
+ */
public void poke() {
if (mIsDozing) {
forcePoke();
}
}
- /** Poke this dozer to wake it up for a little bit. */
+ /**
+ * Poke this dozer to wake it up even if it is not currently dozing.
+ */
void forcePoke() {
mHandler.removeCallbacks(mDozeRunnable);
mHandler.postDelayed(mDozeRunnable, mDozeDurationMilliseconds);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
index c87a901..401b448 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
+import android.util.Log;
import java.util.ArrayList;
@@ -28,6 +29,8 @@
*/
public class ReferenceCountedTrigger {
+ private static final String TAG = "ReferenceCountedTrigger";
+
Context mContext;
int mCount;
ArrayList<Runnable> mFirstIncRunnables = new ArrayList<Runnable>();
@@ -94,8 +97,7 @@
if (mErrorRunnable != null) {
mErrorRunnable.run();
} else {
- new Throwable("Invalid ref count").printStackTrace();
- Console.logError(mContext, "Invalid ref count");
+ Log.e(TAG, "Invalid ref count");
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 4ee0357..0432ac9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -363,6 +363,19 @@
}
}
+ /**
+ * Cancels the current thumbnail transtion to/from Recents for the given task id.
+ */
+ public void cancelThumbnailTransition(int taskId) {
+ if (mWm == null) return;
+
+ try {
+ WindowManagerGlobal.getWindowManagerService().cancelTaskThumbnailTransition(taskId);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
/** Returns the top task thumbnail for the given task id */
public Bitmap getTaskThumbnail(int taskId) {
if (mAm == null) return null;
@@ -775,8 +788,7 @@
taskId, INVALID_STACK_ID, options == null ? null : options.toBundle());
return true;
} catch (Exception e) {
- Console.logError(context,
- context.getString(R.string.recents_launch_error_message, taskName));
+ Log.e(TAG, context.getString(R.string.recents_launch_error_message, taskName), e);
}
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 495c8fd..6734012 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -17,14 +17,12 @@
package com.android.systemui.recents.model;
import android.animation.ObjectAnimator;
-import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
-import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.Recents;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 9a5e141..5f94fa7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -51,6 +51,7 @@
import com.android.systemui.recents.RecentsAppWidgetHostView;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
@@ -64,8 +65,8 @@
import java.util.ArrayList;
import java.util.List;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
/**
@@ -82,7 +83,6 @@
/** The RecentsView callbacks */
public interface RecentsViewCallbacks {
- public void onTaskViewClicked();
public void onTaskLaunchFailed();
public void onAllTaskViewsDismissed();
}
@@ -107,6 +107,7 @@
Rect mSystemInsets = new Rect();
+
@GuardedBy("this")
List<AppTransitionAnimationSpec> mAppTransitionAnimationSpecs;
@@ -246,6 +247,9 @@
}
ctx.postAnimationTrigger.decrement();
+ // If we are going home, cancel the previous task's window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
+
// Notify of the exit animation
EventBus.getDefault().send(new DismissRecentsToHomeAnimationStarted());
}
@@ -555,30 +559,12 @@
return new AppTransitionAnimationSpec(taskId, b, rect);
}
- /**
- * Cancels any running window transitions for the launched task (the task animating into
- * Recents).
- */
- private void cancelLaunchedTaskWindowTransition(final Task task) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- if (launchState.launchedToTaskId != -1 &&
- launchState.launchedToTaskId != task.key.id) {
- ssp.cancelWindowTransition(launchState.launchedToTaskId);
- }
- }
-
/**** TaskStackView.TaskStackCallbacks Implementation ****/
@Override
public void onTaskViewClicked(final TaskStackView stackView, final TaskView tv,
final TaskStack stack, final Task task, final boolean lockToTask,
final boolean boundsValid, final Rect bounds, int destinationStack) {
- // Notify any callbacks of the launching of a new task
- if (mCb != null) {
- mCb.onTaskViewClicked();
- }
// Upfront the processing of the thumbnail
TaskViewTransform transform = new TaskViewTransform();
@@ -610,7 +596,7 @@
public void onAnimationStarted() {
// If we are launching into another task, cancel the previous task's
// window transition
- cancelLaunchedTaskWindowTransition(task);
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
if (lockToTask) {
// Request screen pinning after the animation runs
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 7f5c768..51091c3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -31,7 +31,6 @@
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.LinkedList;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index fc3a681..3ef597f7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -34,7 +34,6 @@
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
@@ -228,6 +227,42 @@
return mImmutableTaskViews;
}
+ /**
+ * Returns the front most task view.
+ *
+ * @param stackTasksOnly if set, will return the front most task view in the stack (by default
+ * the front most task view will be freeform since they are placed above
+ * stack tasks)
+ */
+ private TaskView getFrontMostTaskView(boolean stackTasksOnly) {
+ List<TaskView> taskViews = getTaskViews();
+ int taskViewCount = taskViews.size();
+ for (int i = taskViewCount - 1; i >= 0; i--) {
+ TaskView tv = taskViews.get(i);
+ Task task = tv.getTask();
+ if (stackTasksOnly && task.isFreeformTask()) {
+ continue;
+ }
+ return tv;
+ }
+ return null;
+ }
+
+ /**
+ * Finds the child view given a specific {@param task}.
+ */
+ public TaskView getChildViewForTask(Task t) {
+ List<TaskView> taskViews = getTaskViews();
+ int taskViewCount = taskViews.size();
+ for (int i = 0; i < taskViewCount; i++) {
+ TaskView tv = taskViews.get(i);
+ if (tv.getTask() == t) {
+ return tv;
+ }
+ }
+ return null;
+ }
+
/** Resets this TaskStackView for reuse. */
void reset() {
// Reset the focused task
@@ -288,19 +323,6 @@
}
}
- /** Finds the child view given a specific task. */
- public TaskView getChildViewForTask(Task t) {
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- if (tv.getTask() == t) {
- return tv;
- }
- }
- return null;
- }
-
/** Returns the stack algorithm for this task stack. */
public TaskStackLayoutAlgorithm getStackAlgorithm() {
return mLayoutAlgorithm;
@@ -635,13 +657,49 @@
/**
* Sets the focused task relative to the currently focused task.
*
+ * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and
+ * if the currently focused task is not a stack task, will set the focus
+ * to the first visible stack task
* @param animated determines whether to actually draw the highlight along with the change in
* focus.
*/
- public void setRelativeFocusedTask(boolean forward, boolean animated) {
- // Find the next index to focus
- int newIndex = mFocusedTaskIndex + (forward ? -1 : 1);
- setFocusedTask(newIndex, true, animated);
+ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) {
+ int newIndex = -1;
+ if (mFocusedTaskIndex != -1) {
+ if (stackTasksOnly) {
+ List<Task> tasks = mStack.getTasks();
+ newIndex = mFocusedTaskIndex;
+ Task task = tasks.get(mFocusedTaskIndex);
+ if (task.isFreeformTask()) {
+ // Try and focus the front most stack task
+ TaskView tv = getFrontMostTaskView(stackTasksOnly);
+ if (tv != null) {
+ newIndex = mStack.indexOfTask(tv.getTask());
+ }
+ } else {
+ // Try the next task if it is a stack task
+ int tmpNewIndex = mFocusedTaskIndex + (forward ? -1 : 1);
+ if (0 <= tmpNewIndex && tmpNewIndex < tasks.size()) {
+ Task t = tasks.get(tmpNewIndex);
+ if (!t.isFreeformTask()) {
+ newIndex = tmpNewIndex;
+ }
+ }
+ }
+ } else {
+ // No restrictions, lets just move to the new task
+ newIndex = mFocusedTaskIndex + (forward ? -1 : 1);
+ }
+ } else {
+ // We don't have a focused task, so focus the first visible task view
+ TaskView tv = getFrontMostTaskView(stackTasksOnly);
+ if (tv != null) {
+ newIndex = mStack.indexOfTask(tv.getTask());
+ }
+ }
+ if (newIndex != -1) {
+ setFocusedTask(newIndex, true, animated);
+ }
}
/**
@@ -703,11 +761,11 @@
}
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
- setRelativeFocusedTask(true, false /* animated */);
+ setRelativeFocusedTask(true, false /* stackTasksOnly */, false /* animated */);
return true;
}
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
- setRelativeFocusedTask(false, false /* animated */);
+ setRelativeFocusedTask(false, false /* stackTasksOnly */, false /* animated */);
return true;
}
}
@@ -1324,11 +1382,11 @@
}
public final void onBusEvent(FocusNextTaskViewEvent event) {
- setRelativeFocusedTask(true, true);
+ setRelativeFocusedTask(true, false /* stackTasksOnly */, true /* animated */);
}
public final void onBusEvent(FocusPreviousTaskViewEvent event) {
- setRelativeFocusedTask(false, true);
+ setRelativeFocusedTask(false, false /* stackTasksOnly */, true /* animated */);
}
public final void onBusEvent(DismissFocusedTaskViewEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewFilterAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewFilterAlgorithm.java
index a32b242..45f573d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewFilterAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewFilterAlgorithm.java
@@ -17,7 +17,6 @@
package com.android.systemui.recents.views;
import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
import com.android.systemui.recents.model.Task;
import java.util.ArrayList;
@@ -113,7 +112,7 @@
tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
tv.updateViewPropertiesToTaskTransform(fromTransform, 0);
- toTransform.startDelay = offset * Constants.Values.TaskStackView.FilterStartDelay;
+ toTransform.startDelay = offset * 25;
childViewTransformsOut.put(tv, toTransform);
// Use the movement of the new views to calculate the duration of the animation
@@ -166,7 +165,7 @@
(int) tv.getTranslationY()));
}
- toTransform.startDelay = offset * Constants.Values.TaskStackView.FilterStartDelay;
+ toTransform.startDelay = offset * 25;
childViewTransformsOut.put(tv, toTransform);
offset++;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 59c9708..81c89a1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -31,6 +31,7 @@
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
@@ -149,6 +150,11 @@
if (mSv.getTaskViews().size() == 0) {
return false;
}
+ // Short circuit while we are alt-tabbing
+ RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+ if (launchState.launchedWithAltTab) {
+ return false;
+ }
final TaskStackLayoutAlgorithm layoutAlgorithm = mSv.mLayoutAlgorithm;
int action = ev.getAction();
@@ -305,9 +311,11 @@
// Find the front most task and scroll the next task to the front
float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
if (vScroll > 0) {
- mSv.setRelativeFocusedTask(true, false /* animated */);
+ mSv.setRelativeFocusedTask(true, true /* stackTasksOnly */,
+ false /* animated */);
} else {
- mSv.setRelativeFocusedTask(false, false /* animated */);
+ mSv.setRelativeFocusedTask(false, true /* stackTasksOnly */,
+ false /* animated */);
}
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index dd1474d..4f4b91a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -29,6 +29,7 @@
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -80,7 +81,6 @@
boolean mTaskDataLoaded;
boolean mIsFocused;
boolean mIsFocusAnimated;
- boolean mFocusAnimationsEnabled;
boolean mClipViewInStack;
AnimateableViewBounds mViewBounds;
@@ -642,6 +642,21 @@
setDim(getDimFromTaskProgress());
}
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ if (Constants.DebugFlags.App.EnableFastToggleRecents && mIsFocused) {
+ Paint tmpPaint = new Paint();
+ Rect tmpRect = new Rect();
+ tmpRect.set(0, 0, getWidth(), getHeight());
+ tmpPaint.setColor(0xFFFF0000);
+ tmpPaint.setStrokeWidth(35);
+ tmpPaint.setStyle(Paint.Style.STROKE);
+ canvas.drawRect(tmpRect, tmpPaint);
+ }
+ }
+
/**** View focus state ****/
/**
@@ -672,6 +687,9 @@
clearAccessibilityFocus();
}
}
+ if (Constants.DebugFlags.App.EnableFastToggleRecents) {
+ invalidate();
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 3d6c600..59d4011 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -303,6 +303,10 @@
if (mTmpRect.equals(mLastResizeRect)) {
return;
}
+
+ // Make sure shadows are updated
+ mBackground.invalidate();
+
mLastResizeRect.set(mTmpRect);
mWindowManagerProxy.resizeDockedStack(mTmpRect);
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index c35b91f..031f6d2 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -319,7 +319,7 @@
mCallingPackage = callingPackage;
mResizeable = resizeable || mService.mForceResizableActivites;
mPrivileged = privileged;
- ActivityInfo info = mActivities.get(0).info;
+ ActivityInfo info = (mActivities.size() > 0) ? mActivities.get(0).info : null;
mMinimalSize = info != null && info.layout != null ? info.layout.minimalSize : -1;
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 0fb82b3..4929960 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -635,7 +635,7 @@
}
if (info != null && (info.flags&UserInfo.FLAG_INITIALIZED) == 0) {
info.flags |= UserInfo.FLAG_INITIALIZED;
- scheduleWriteUserLP(info);
+ scheduleWriteUser(info);
}
}
}
@@ -775,6 +775,7 @@
Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
!= newRestrictions);
mBaseUserRestrictions.put(userId, newRestrictions);
+ scheduleWriteUser(mUsers.get(userId));
}
final Bundle effective = computeEffectiveUserRestrictionsLR(userId);
@@ -1082,7 +1083,7 @@
UserInfo user = getUserInfoNoChecks(UserHandle.USER_SYSTEM);
if ("Primary".equals(user.name)) {
user.name = mContext.getResources().getString(com.android.internal.R.string.owner_name);
- scheduleWriteUserLP(user);
+ scheduleWriteUser(user);
}
userVersion = 1;
}
@@ -1092,7 +1093,7 @@
UserInfo user = getUserInfoNoChecks(UserHandle.USER_SYSTEM);
if ((user.flags & UserInfo.FLAG_INITIALIZED) == 0) {
user.flags |= UserInfo.FLAG_INITIALIZED;
- scheduleWriteUserLP(user);
+ scheduleWriteUser(user);
}
userVersion = 2;
}
@@ -1116,7 +1117,7 @@
if (!splitSystemUser && user.isRestricted()
&& (user.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID)) {
user.restrictedProfileParentId = UserHandle.USER_SYSTEM;
- scheduleWriteUserLP(user);
+ scheduleWriteUser(user);
}
}
}
@@ -1161,7 +1162,9 @@
writeUserLP(system);
}
- private void scheduleWriteUserLP(UserInfo userInfo) {
+ private void scheduleWriteUser(UserInfo userInfo) {
+ // No need to wrap it within a lock -- worst case, we'll just post the same message
+ // twice.
if (!mHandler.hasMessages(WRITE_USER_MSG, userInfo)) {
Message msg = mHandler.obtainMessage(WRITE_USER_MSG, userInfo);
mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY);
@@ -1543,7 +1546,7 @@
if (isManagedProfile) {
if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
parent.profileGroupId = parent.id;
- scheduleWriteUserLP(parent);
+ scheduleWriteUser(parent);
}
userInfo.profileGroupId = parent.profileGroupId;
} else if (isRestricted) {
@@ -1552,7 +1555,7 @@
}
if (parent.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) {
parent.restrictedProfileParentId = parent.id;
- scheduleWriteUserLP(parent);
+ scheduleWriteUser(parent);
}
userInfo.restrictedProfileParentId = parent.restrictedProfileParentId;
}
@@ -1571,7 +1574,7 @@
}
mPm.createNewUserLILPw(userId);
userInfo.partial = false;
- scheduleWriteUserLP(userInfo);
+ scheduleWriteUser(userInfo);
updateUserIds();
Bundle restrictions = new Bundle();
synchronized (mRestrictionsLock) {
@@ -2148,7 +2151,7 @@
}
if (now > EPOCH_PLUS_30_YEARS) {
user.lastLoggedInTime = now;
- scheduleWriteUserLP(user);
+ scheduleWriteUser(user);
}
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 5864b25..6aaf3c7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -328,6 +328,15 @@
}
}
+ /**
+ * Cancels any running thumbnail transitions associated with the task.
+ */
+ void cancelTaskThumbnailTransition() {
+ for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
+ mAppTokens.get(activityNdx).mAppAnimator.clearThumbnail();
+ }
+ }
+
boolean showForAllUsers() {
final int tokensCount = mAppTokens.size();
return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index bc34ba7..3205c6c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4690,6 +4690,16 @@
}
}
+ @Override
+ public void cancelTaskThumbnailTransition(int taskId) {
+ synchronized (mWindowMap) {
+ Task task = mTaskIdToTask.get(taskId);
+ if (task != null) {
+ task.cancelTaskThumbnailTransition();
+ }
+ }
+ }
+
public void addTask(int taskId, int stackId, boolean toTop) {
synchronized (mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
index 9a1fe15..11d8136 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
@@ -100,16 +100,14 @@
* SSLHandshakeException when used for a connection.
*/
private NetworkSecurityConfig getEmptyConfig() {
- return new NetworkSecurityConfig(true, false,
- new PinSet(new ArraySet<Pin>(), -1),
- new ArrayList<CertificatesEntryRef>());
+ return new NetworkSecurityConfig.Builder().build();
}
private NetworkSecurityConfig getSystemStoreConfig() {
- ArrayList<CertificatesEntryRef> defaultSource = new ArrayList<CertificatesEntryRef>();
- defaultSource.add(new CertificatesEntryRef(new SystemCertificateSource(), false));
- return new NetworkSecurityConfig(true, false, new PinSet(new ArraySet<Pin>(),
- -1), defaultSource);
+ return new NetworkSecurityConfig.Builder()
+ .addCertificatesEntryRef(
+ new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ .build();
}
public void testEmptyConfig() throws Exception {
@@ -126,24 +124,20 @@
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
new Domain("android.com", true), getEmptyConfig()));
- ArrayList<CertificatesEntryRef> defaultSource = new ArrayList<CertificatesEntryRef>();
- defaultSource.add(new CertificatesEntryRef(new SystemCertificateSource(), false));
- NetworkSecurityConfig defaultConfig = new NetworkSecurityConfig(true, false,
- new PinSet(new ArraySet<Pin>(), -1),
- defaultSource);
+ NetworkSecurityConfig defaultConfig = getSystemStoreConfig();
SSLContext context = getSSLContext(new TestConfigSource(domainMap, defaultConfig));
assertConnectionFails(context, "android.com", 443);
assertConnectionSucceeds(context, "google.com", 443);
}
public void testBadPin() throws Exception {
- ArrayList<CertificatesEntryRef> systemSource = new ArrayList<CertificatesEntryRef>();
- systemSource.add(new CertificatesEntryRef(new SystemCertificateSource(), false));
ArraySet<Pin> pins = new ArraySet<Pin>();
pins.add(new Pin("SHA-256", new byte[0]));
- NetworkSecurityConfig domain = new NetworkSecurityConfig(true, false,
- new PinSet(pins, Long.MAX_VALUE),
- systemSource);
+ NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
+ .setPinSet(new PinSet(pins, Long.MAX_VALUE))
+ .addCertificatesEntryRef(
+ new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ .build();
ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
@@ -155,13 +149,13 @@
}
public void testGoodPin() throws Exception {
- ArrayList<CertificatesEntryRef> systemSource = new ArrayList<CertificatesEntryRef>();
- systemSource.add(new CertificatesEntryRef(new SystemCertificateSource(), false));
ArraySet<Pin> pins = new ArraySet<Pin>();
pins.add(new Pin("SHA-256", G2_SPKI_SHA256));
- NetworkSecurityConfig domain = new NetworkSecurityConfig(true, false,
- new PinSet(pins, Long.MAX_VALUE),
- systemSource);
+ NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
+ .setPinSet(new PinSet(pins, Long.MAX_VALUE))
+ .addCertificatesEntryRef(
+ new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ .build();
ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
@@ -174,13 +168,13 @@
public void testOverridePins() throws Exception {
// Use a bad pin + granting the system CA store the ability to override pins.
- ArrayList<CertificatesEntryRef> systemSource = new ArrayList<CertificatesEntryRef>();
- systemSource.add(new CertificatesEntryRef(new SystemCertificateSource(), true));
ArraySet<Pin> pins = new ArraySet<Pin>();
pins.add(new Pin("SHA-256", new byte[0]));
- NetworkSecurityConfig domain = new NetworkSecurityConfig(true, false,
- new PinSet(pins, Long.MAX_VALUE),
- systemSource);
+ NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
+ .setPinSet(new PinSet(pins, Long.MAX_VALUE))
+ .addCertificatesEntryRef(
+ new CertificatesEntryRef(SystemCertificateSource.getInstance(), true))
+ .build();
ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
@@ -220,14 +214,33 @@
assertConnectionFails(context, "developer.android.com", 443);
}
+ public void testConfigBuilderUsesParents() throws Exception {
+ // Check that a builder with a parent uses the parent's values when non is set.
+ NetworkSecurityConfig config = new NetworkSecurityConfig.Builder()
+ .setParent(NetworkSecurityConfig.getDefaultBuilder())
+ .build();
+ assert(!config.getTrustAnchors().isEmpty());
+ }
+
+ public void testConfigBuilderParentLoop() throws Exception {
+ NetworkSecurityConfig.Builder config1 = new NetworkSecurityConfig.Builder();
+ NetworkSecurityConfig.Builder config2 = new NetworkSecurityConfig.Builder();
+ config1.setParent(config2);
+ try {
+ config2.setParent(config1);
+ fail("Loop in NetworkSecurityConfig parents");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
public void testWithUrlConnection() throws Exception {
- ArrayList<CertificatesEntryRef> systemSource = new ArrayList<CertificatesEntryRef>();
- systemSource.add(new CertificatesEntryRef(new SystemCertificateSource(), false));
ArraySet<Pin> pins = new ArraySet<Pin>();
pins.add(new Pin("SHA-256", G2_SPKI_SHA256));
- NetworkSecurityConfig domain = new NetworkSecurityConfig(true, false,
- new PinSet(pins, Long.MAX_VALUE),
- systemSource);
+ NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
+ .setPinSet(new PinSet(pins, Long.MAX_VALUE))
+ .addCertificatesEntryRef(
+ new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ .build();
ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
domainMap.add(new Pair<Domain, NetworkSecurityConfig>(
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index ceed21e..ec29c38 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -80,6 +80,7 @@
util/StringPiece_test.cpp \
util/Util_test.cpp \
ConfigDescription_test.cpp \
+ java/AnnotationProcessor_test.cpp \
java/JavaClassGenerator_test.cpp \
java/ManifestClassGenerator_test.cpp \
Locale_test.cpp \
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 39a4116..5172fab 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -973,7 +973,7 @@
const Source source = mSource.withLine(parser->getLineNumber());
std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
- // Declare-styleable is always public, because it technically only exists in R.java.
+ // Declare-styleable is kPrivate by default, because it technically only exists in R.java.
outResource->symbolState = SymbolState::kPublic;
std::u16string comment;
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index fa4b109..deafe20 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -284,7 +284,7 @@
}
const auto endIter = entry->values.end();
- auto iter = std::lower_bound(entry->values.begin(), endIter, config, cmp::lessThan);
+ auto iter = std::lower_bound(entry->values.begin(), endIter, config, cmp::lessThanConfig);
if (iter == endIter || iter->config != config) {
// This resource did not exist before, add it.
entry->values.insert(iter, ResourceConfigValue{ config, std::move(value) });
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index f312d75..8acff0d 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -44,7 +44,10 @@
}
RawString* RawString::clone(StringPool* newPool) const {
- return new RawString(newPool->makeRef(*value));
+ RawString* rs = new RawString(newPool->makeRef(*value));
+ rs->mComment = mComment;
+ rs->mSource = mSource;
+ return rs;
}
bool RawString::flatten(android::Res_value* outValue) const {
@@ -77,6 +80,8 @@
Reference* Reference::clone(StringPool* /*newPool*/) const {
Reference* ref = new Reference();
+ ref->mComment = mComment;
+ ref->mSource = mSource;
ref->referenceType = referenceType;
ref->name = name;
ref->id = id;
@@ -111,7 +116,10 @@
}
Id* Id::clone(StringPool* /*newPool*/) const {
- return new Id();
+ Id* id = new Id();
+ id->mComment = mComment;
+ id->mSource = mSource;
+ return id;
}
void Id::print(std::ostream* out) const {
@@ -133,7 +141,10 @@
}
String* String::clone(StringPool* newPool) const {
- return new String(newPool->makeRef(*value));
+ String* str = new String(newPool->makeRef(*value));
+ str->mComment = mComment;
+ str->mSource = mSource;
+ return str;
}
void String::print(std::ostream* out) const {
@@ -154,7 +165,10 @@
}
StyledString* StyledString::clone(StringPool* newPool) const {
- return new StyledString(newPool->makeRef(value));
+ StyledString* str = new StyledString(newPool->makeRef(value));
+ str->mComment = mComment;
+ str->mSource = mSource;
+ return str;
}
void StyledString::print(std::ostream* out) const {
@@ -175,7 +189,10 @@
}
FileReference* FileReference::clone(StringPool* newPool) const {
- return new FileReference(newPool->makeRef(*path));
+ FileReference* fr = new FileReference(newPool->makeRef(*path));
+ fr->mComment = mComment;
+ fr->mSource = mSource;
+ return fr;
}
void FileReference::print(std::ostream* out) const {
@@ -197,7 +214,10 @@
}
BinaryPrimitive* BinaryPrimitive::clone(StringPool* /*newPool*/) const {
- return new BinaryPrimitive(value);
+ BinaryPrimitive* bp = new BinaryPrimitive(value);
+ bp->mComment = mComment;
+ bp->mSource = mSource;
+ return bp;
}
void BinaryPrimitive::print(std::ostream* out) const {
@@ -236,6 +256,8 @@
Attribute* Attribute::clone(StringPool* /*newPool*/) const {
Attribute* attr = new Attribute(weak);
+ attr->mComment = mComment;
+ attr->mSource = mSource;
attr->typeMask = typeMask;
std::copy(symbols.begin(), symbols.end(), std::back_inserter(attr->symbols));
return attr;
@@ -358,6 +380,8 @@
Style* style = new Style();
style->parent = parent;
style->parentInferred = parentInferred;
+ style->mComment = mComment;
+ style->mSource = mSource;
for (auto& entry : entries) {
style->entries.push_back(Entry{
entry.key,
@@ -390,6 +414,8 @@
Array* Array::clone(StringPool* newPool) const {
Array* array = new Array();
+ array->mComment = mComment;
+ array->mSource = mSource;
for (auto& item : items) {
array->items.emplace_back(std::unique_ptr<Item>(item->clone(newPool)));
}
@@ -404,6 +430,8 @@
Plural* Plural::clone(StringPool* newPool) const {
Plural* p = new Plural();
+ p->mComment = mComment;
+ p->mSource = mSource;
const size_t count = values.size();
for (size_t i = 0; i < count; i++) {
if (values[i]) {
@@ -423,6 +451,8 @@
Styleable* Styleable::clone(StringPool* /*newPool*/) const {
Styleable* styleable = new Styleable();
+ styleable->mComment = mComment;
+ styleable->mSource = mSource;
std::copy(entries.begin(), entries.end(), std::back_inserter(styleable->entries));
return styleable;
}
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 2629153..7ae346a 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -91,7 +91,7 @@
*/
virtual void print(std::ostream* out) const = 0;
-private:
+protected:
Source mSource;
std::u16string mComment;
};
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index b36682d..9c25d4e 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -25,33 +25,20 @@
static const std::string sDeprecated = "@deprecated";
static const std::string sSystemApi = "@SystemApi";
- if (comment.find(sDeprecated) != std::string::npos && !mDeprecated) {
- mDeprecated = true;
- if (!mAnnotations.empty()) {
- mAnnotations += "\n";
- }
- mAnnotations += mPrefix;
- mAnnotations += "@Deprecated";
+ if (comment.find(sDeprecated) != std::string::npos) {
+ mAnnotationBitMask |= kDeprecated;
}
- if (comment.find(sSystemApi) != std::string::npos && !mSystemApi) {
- mSystemApi = true;
- if (!mAnnotations.empty()) {
- mAnnotations += "\n";
- }
- mAnnotations += mPrefix;
- mAnnotations += "@android.annotations.SystemApi";
+ if (comment.find(sSystemApi) != std::string::npos) {
+ mAnnotationBitMask |= kSystemApi;
}
- if (mComment.empty()) {
- mComment += mPrefix;
- mComment += "/**";
+ if (!mHasComments) {
+ mHasComments = true;
+ mComment << "/**";
}
- mComment += "\n";
- mComment += mPrefix;
- mComment += " * ";
- mComment += std::move(comment);
+ mComment << "\n" << " * " << std::move(comment);
}
void AnnotationProcessor::appendComment(const StringPiece16& comment) {
@@ -73,17 +60,22 @@
}
}
-std::string AnnotationProcessor::buildComment() {
- if (!mComment.empty()) {
- mComment += "\n";
- mComment += mPrefix;
- mComment += " */";
+void AnnotationProcessor::writeToStream(std::ostream* out, const StringPiece& prefix) {
+ if (mHasComments) {
+ std::string result = mComment.str();
+ for (StringPiece line : util::tokenize<char>(result, '\n')) {
+ *out << prefix << line << "\n";
+ }
+ *out << prefix << " */" << "\n";
}
- return std::move(mComment);
-}
-std::string AnnotationProcessor::buildAnnotations() {
- return std::move(mAnnotations);
+ if (mAnnotationBitMask & kDeprecated) {
+ *out << prefix << "@Deprecated\n";
+ }
+
+ if (mAnnotationBitMask & kSystemApi) {
+ *out << prefix << "@android.annotation.SystemApi\n";
+ }
}
} // namespace aapt
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index 81a6f6e..e7f2be0 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -19,6 +19,7 @@
#include "util/StringPiece.h"
+#include <sstream>
#include <string>
namespace aapt {
@@ -54,13 +55,6 @@
class AnnotationProcessor {
public:
/**
- * Creates an AnnotationProcessor with a given prefix for each line generated.
- * This is usually a set of spaces for indentation.
- */
- AnnotationProcessor(const StringPiece& prefix) : mPrefix(prefix.toString()) {
- }
-
- /**
* Adds more comments. Since resources can have various values with different configurations,
* we need to collect all the comments.
*/
@@ -68,23 +62,20 @@
void appendComment(const StringPiece& comment);
/**
- * Finishes the comment and moves it to the caller. Subsequent calls to buildComment() have
- * undefined results.
+ * Writes the comments and annotations to the stream, with the given prefix before each line.
*/
- std::string buildComment();
-
- /**
- * Finishes the annotation and moves it to the caller. Subsequent calls to buildAnnotations()
- * have undefined results.
- */
- std::string buildAnnotations();
+ void writeToStream(std::ostream* out, const StringPiece& prefix);
private:
- std::string mPrefix;
- std::string mComment;
- std::string mAnnotations;
- bool mDeprecated = false;
- bool mSystemApi = false;
+ enum : uint32_t {
+ kDeprecated = 0x01,
+ kSystemApi = 0x02,
+ };
+
+ std::stringstream mComment;
+ std::stringstream mAnnotations;
+ bool mHasComments = false;
+ uint32_t mAnnotationBitMask = 0;
void appendCommentLine(const std::string& line);
};
diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp
new file mode 100644
index 0000000..d5a2b38
--- /dev/null
+++ b/tools/aapt2/java/AnnotationProcessor_test.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "ResourceParser.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "XmlPullParser.h"
+
+#include "java/AnnotationProcessor.h"
+
+#include "test/Builders.h"
+#include "test/Context.h"
+
+#include <gtest/gtest.h>
+
+namespace aapt {
+
+struct AnnotationProcessorTest : public ::testing::Test {
+ std::unique_ptr<IAaptContext> mContext;
+ ResourceTable mTable;
+
+ void SetUp() override {
+ mContext = test::ContextBuilder().build();
+ }
+
+ ::testing::AssertionResult parse(const StringPiece& str) {
+ ResourceParserOptions options;
+ ResourceParser parser(mContext->getDiagnostics(), &mTable, Source{}, ConfigDescription{},
+ options);
+ std::stringstream in;
+ in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str;
+ XmlPullParser xmlParser(in);
+ if (parser.parse(&xmlParser)) {
+ return ::testing::AssertionSuccess();
+ }
+ return ::testing::AssertionFailure();
+ }
+};
+
+TEST_F(AnnotationProcessorTest, EmitsDeprecated) {
+ ASSERT_TRUE(parse(R"EOF(
+ <resources>
+ <declare-styleable name="foo">
+ <!-- Some comment, and it should contain
+ a marker word, something that marks
+ this resource as nor needed.
+ {@deprecated That's the marker! } -->
+ <attr name="autoText" format="boolean" />
+ </declare-styleable>
+ </resources>)EOF"));
+
+ Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/autoText");
+ ASSERT_NE(nullptr, attr);
+
+ AnnotationProcessor processor;
+ processor.appendComment(attr->getComment());
+
+ std::stringstream result;
+ processor.writeToStream(&result, "");
+ std::string annotations = result.str();
+
+ EXPECT_NE(std::string::npos, annotations.find("@Deprecated"));
+}
+
+} // namespace aapt
+
+
diff --git a/tools/aapt2/java/ClassDefinitionWriter.h b/tools/aapt2/java/ClassDefinitionWriter.h
new file mode 100644
index 0000000..b8886f9
--- /dev/null
+++ b/tools/aapt2/java/ClassDefinitionWriter.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef AAPT_JAVA_CLASSDEFINITION_H
+#define AAPT_JAVA_CLASSDEFINITION_H
+
+#include "java/AnnotationProcessor.h"
+#include "util/StringPiece.h"
+#include "util/Util.h"
+
+#include <sstream>
+#include <string>
+
+namespace aapt {
+
+struct ClassDefinitionWriterOptions {
+ bool useFinalQualifier = false;
+ bool forceCreationIfEmpty = false;
+};
+
+/**
+ * Writes a class for use in R.java or Manifest.java.
+ */
+class ClassDefinitionWriter {
+public:
+ ClassDefinitionWriter(const StringPiece& name, const ClassDefinitionWriterOptions& options) :
+ mName(name.toString()), mOptions(options), mStarted(false) {
+ }
+
+ ClassDefinitionWriter(const StringPiece16& name, const ClassDefinitionWriterOptions& options) :
+ mName(util::utf16ToUtf8(name)), mOptions(options), mStarted(false) {
+ }
+
+ void addIntMember(const StringPiece& name, AnnotationProcessor* processor,
+ const uint32_t val) {
+ ensureClassDeclaration();
+ if (processor) {
+ processor->writeToStream(&mOut, kIndent);
+ }
+ mOut << kIndent << "public static " << (mOptions.useFinalQualifier ? "final " : "")
+ << "int " << name << "=" << val << ";\n";
+ }
+
+ void addStringMember(const StringPiece16& name, AnnotationProcessor* processor,
+ const StringPiece16& val) {
+ ensureClassDeclaration();
+ if (processor) {
+ processor->writeToStream(&mOut, kIndent);
+ }
+ mOut << kIndent << "public static " << (mOptions.useFinalQualifier ? "final " : "")
+ << "String " << name << "=\"" << val << "\";\n";
+ }
+
+ void addResourceMember(const StringPiece16& name, AnnotationProcessor* processor,
+ const ResourceId id) {
+ ensureClassDeclaration();
+ if (processor) {
+ processor->writeToStream(&mOut, kIndent);
+ }
+ mOut << kIndent << "public static " << (mOptions.useFinalQualifier ? "final " : "")
+ << "int " << name << "=" << id <<";\n";
+ }
+
+ template <typename Iterator, typename FieldAccessorFunc>
+ void addArrayMember(const StringPiece16& name, AnnotationProcessor* processor,
+ const Iterator begin, const Iterator end, FieldAccessorFunc f) {
+ ensureClassDeclaration();
+ if (processor) {
+ processor->writeToStream(&mOut, kIndent);
+ }
+ mOut << kIndent << "public static final int[] " << name << "={";
+
+ for (Iterator current = begin; current != end; ++current) {
+ if (std::distance(begin, current) % kAttribsPerLine == 0) {
+ mOut << "\n" << kIndent << kIndent;
+ }
+
+ mOut << f(*current);
+ if (std::distance(current, end) > 1) {
+ mOut << ", ";
+ }
+ }
+ mOut << "\n" << kIndent <<"};\n";
+ }
+
+ void writeToStream(std::ostream* out, const StringPiece& prefix,
+ AnnotationProcessor* processor=nullptr) {
+ if (mOptions.forceCreationIfEmpty) {
+ ensureClassDeclaration();
+ }
+
+ if (!mStarted) {
+ return;
+ }
+
+ if (processor) {
+ processor->writeToStream(out, prefix);
+ }
+
+ std::string result = mOut.str();
+ for (StringPiece line : util::tokenize<char>(result, '\n')) {
+ *out << prefix << line << "\n";
+ }
+ *out << prefix << "}\n";
+ }
+
+private:
+ constexpr static const char* kIndent = " ";
+
+ // The number of attributes to emit per line in a Styleable array.
+ constexpr static size_t kAttribsPerLine = 4;
+
+ void ensureClassDeclaration() {
+ if (!mStarted) {
+ mStarted = true;
+ mOut << "public static final class " << mName << " {\n";
+ }
+ }
+
+ std::stringstream mOut;
+ std::string mName;
+ ClassDefinitionWriterOptions mOptions;
+ bool mStarted;
+};
+
+} // namespace aapt
+
+#endif /* AAPT_JAVA_CLASSDEFINITION_H */
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index dfd2ef6..7280f3a 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -21,7 +21,9 @@
#include "ValueVisitor.h"
#include "java/AnnotationProcessor.h"
+#include "java/ClassDefinitionWriter.h"
#include "java/JavaClassGenerator.h"
+#include "util/Comparators.h"
#include "util/StringPiece.h"
#include <algorithm>
@@ -32,9 +34,6 @@
namespace aapt {
-// The number of attributes to emit per line in a Styleable array.
-constexpr size_t kAttribsPerLine = 4;
-
JavaClassGenerator::JavaClassGenerator(ResourceTable* table, JavaClassGeneratorOptions options) :
mTable(table), mOptions(options) {
}
@@ -92,12 +91,11 @@
return true;
}
-void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGenerate,
- const std::u16string& entryName,
- const Styleable* styleable,
- std::ostream* out) {
- const StringPiece finalModifier = mOptions.useFinal ? " final" : "";
-
+void JavaClassGenerator::writeStyleableEntryForClass(ClassDefinitionWriter* outClassDef,
+ AnnotationProcessor* processor,
+ const StringPiece16& packageNameToGenerate,
+ const std::u16string& entryName,
+ const Styleable* styleable) {
// This must be sorted by resource ID.
std::vector<std::pair<ResourceId, ResourceNameRef>> sortedAttributes;
sortedAttributes.reserve(styleable->entries.size());
@@ -110,36 +108,31 @@
}
std::sort(sortedAttributes.begin(), sortedAttributes.end());
+ auto accessorFunc = [](const std::pair<ResourceId, ResourceNameRef>& a) -> ResourceId {
+ return a.first;
+ };
+
// First we emit the array containing the IDs of each attribute.
- *out << " "
- << "public static final int[] " << transform(entryName) << " = {";
-
- const size_t attrCount = sortedAttributes.size();
- for (size_t i = 0; i < attrCount; i++) {
- if (i % kAttribsPerLine == 0) {
- *out << "\n ";
- }
-
- *out << sortedAttributes[i].first;
- if (i != attrCount - 1) {
- *out << ", ";
- }
- }
- *out << "\n };\n";
+ outClassDef->addArrayMember(transform(entryName), processor,
+ sortedAttributes.begin(),
+ sortedAttributes.end(),
+ accessorFunc);
// Now we emit the indices into the array.
+ size_t attrCount = sortedAttributes.size();
for (size_t i = 0; i < attrCount; i++) {
- *out << " "
- << "public static" << finalModifier
- << " int " << transform(entryName);
+ std::stringstream name;
+ name << transform(entryName);
// We may reference IDs from other packages, so prefix the entry name with
// the package.
const ResourceNameRef& itemName = sortedAttributes[i].second;
if (!itemName.package.empty() && packageNameToGenerate != itemName.package) {
- *out << "_" << transform(itemName.package);
+ name << "_" << transform(itemName.package);
}
- *out << "_" << transform(itemName.entry) << " = " << i << ";\n";
+ name << "_" << transform(itemName.entry);
+
+ outClassDef->addIntMember(name.str(), nullptr, i);
}
}
@@ -155,8 +148,8 @@
if (typeMask & android::ResTable_map::TYPE_STRING) {
processor->appendComment(
- "<p>May be a string value, using '\\;' to escape characters such as\n"
- "'\\n' or '\\uxxxx' for a unicode character;");
+ "<p>May be a string value, using '\\\\;' to escape characters such as\n"
+ "'\\\\n' or '\\\\uxxxx' for a unicode character;");
}
if (typeMask & android::ResTable_map::TYPE_INTEGER) {
@@ -222,14 +215,10 @@
}
}
-bool JavaClassGenerator::generateType(const StringPiece16& packageNameToGenerate,
- const ResourceTablePackage* package,
- const ResourceTableType* type,
- std::ostream* out) {
- const StringPiece finalModifier = mOptions.useFinal ? " final" : "";
-
- std::u16string unmangledPackage;
- std::u16string unmangledName;
+bool JavaClassGenerator::writeEntriesForClass(ClassDefinitionWriter* outClassDef,
+ const StringPiece16& packageNameToGenerate,
+ const ResourceTablePackage* package,
+ const ResourceTableType* type) {
for (const auto& entry : type->entries) {
if (skipSymbol(entry->symbolStatus.state)) {
continue;
@@ -238,7 +227,8 @@
ResourceId id(package->id.value(), type->id.value(), entry->id.value());
assert(id.isValid());
- unmangledName = entry->name;
+ std::u16string unmangledPackage;
+ std::u16string unmangledName = entry->name;
if (NameMangler::unmangle(&unmangledName, &unmangledPackage)) {
// The entry name was mangled, and we successfully unmangled it.
// Check that we want to emit this symbol.
@@ -246,12 +236,10 @@
// Skip the entry if it doesn't belong to the package we're writing.
continue;
}
- } else {
- if (packageNameToGenerate != package->name) {
- // We are processing a mangled package name,
- // but this is a non-mangled resource.
- continue;
- }
+ } else if (packageNameToGenerate != package->name) {
+ // We are processing a mangled package name,
+ // but this is a non-mangled resource.
+ continue;
}
if (!isValidSymbol(unmangledName)) {
@@ -262,39 +250,33 @@
return false;
}
+ // Build the comments and annotations for this entry.
+
+ AnnotationProcessor processor;
+ if (entry->symbolStatus.state != SymbolState::kUndefined) {
+ processor.appendComment(entry->symbolStatus.comment);
+ }
+
+ for (const auto& configValue : entry->values) {
+ processor.appendComment(configValue.value->getComment());
+ }
+
+ // If this is an Attribute, append the format Javadoc.
+ if (!entry->values.empty()) {
+ if (Attribute* attr = valueCast<Attribute>(entry->values.front().value.get())) {
+ // We list out the available values for the given attribute.
+ addAttributeFormatDoc(&processor, attr);
+ }
+ }
+
if (type->type == ResourceType::kStyleable) {
assert(!entry->values.empty());
- generateStyleable(packageNameToGenerate, unmangledName, static_cast<const Styleable*>(
- entry->values.front().value.get()), out);
+ const Styleable* styleable = static_cast<const Styleable*>(
+ entry->values.front().value.get());
+ writeStyleableEntryForClass(outClassDef, &processor, packageNameToGenerate,
+ unmangledName, styleable);
} else {
- AnnotationProcessor processor(" ");
- if (entry->symbolStatus.state != SymbolState::kUndefined) {
- processor.appendComment(entry->symbolStatus.comment);
- }
-
- for (const auto& configValue : entry->values) {
- processor.appendComment(configValue.value->getComment());
- }
-
- if (!entry->values.empty()) {
- if (Attribute* attr = valueCast<Attribute>(entry->values.front().value.get())) {
- // We list out the available values for the given attribute.
- addAttributeFormatDoc(&processor, attr);
- }
- }
-
- std::string comment = processor.buildComment();
- if (!comment.empty()) {
- *out << comment << "\n";
- }
-
- std::string annotations = processor.buildAnnotations();
- if (!annotations.empty()) {
- *out << annotations << "\n";
- }
-
- *out << " " << "public static" << finalModifier
- << " int " << transform(unmangledName) << " = " << id << ";\n";
+ outClassDef->addResourceMember(transform(unmangledName), &processor, id);
}
}
return true;
@@ -312,17 +294,42 @@
for (const auto& package : mTable->packages) {
for (const auto& type : package->types) {
- StringPiece16 typeStr;
if (type->type == ResourceType::kAttrPrivate) {
- typeStr = toString(ResourceType::kAttr);
- } else {
- typeStr = toString(type->type);
+ continue;
}
- *out << " public static final class " << typeStr << " {\n";
- if (!generateType(packageNameToGenerate, package.get(), type.get(), out)) {
+
+ ClassDefinitionWriterOptions classOptions;
+ classOptions.useFinalQualifier = mOptions.useFinal;
+ classOptions.forceCreationIfEmpty =
+ (mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic);
+ ClassDefinitionWriter classDef(toString(type->type), classOptions);
+ bool result = writeEntriesForClass(&classDef, packageNameToGenerate,
+ package.get(), type.get());
+ if (!result) {
return false;
}
- *out << " }\n";
+
+ if (type->type == ResourceType::kAttr) {
+ // Also include private attributes in this same class.
+ auto iter = std::lower_bound(package->types.begin(), package->types.end(),
+ ResourceType::kAttrPrivate, cmp::lessThanType);
+ if (iter != package->types.end() && (*iter)->type == ResourceType::kAttrPrivate) {
+ result = writeEntriesForClass(&classDef, packageNameToGenerate,
+ package.get(), iter->get());
+ if (!result) {
+ return false;
+ }
+ }
+ }
+
+ AnnotationProcessor processor;
+ if (type->type == ResourceType::kStyleable &&
+ mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic) {
+ // When generating a public R class, we don't want Styleable to be part of the API.
+ // It is only emitted for documentation purposes.
+ processor.appendComment("@doconly");
+ }
+ classDef.writeToStream(out, " ", &processor);
}
}
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index e53a765..023d6d6 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -27,6 +27,9 @@
namespace aapt {
+class AnnotationProcessor;
+class ClassDefinitionWriter;
+
struct JavaClassGeneratorOptions {
/*
* Specifies whether to use the 'final' modifier
@@ -40,9 +43,6 @@
kPublic,
};
- /*
- *
- */
SymbolTypes types = SymbolTypes::kAll;
};
@@ -69,15 +69,16 @@
const std::string& getError() const;
private:
- bool generateType(const StringPiece16& packageNameToGenerate,
- const ResourceTablePackage* package,
- const ResourceTableType* type,
- std::ostream* out);
+ bool writeEntriesForClass(ClassDefinitionWriter* outClassDef,
+ const StringPiece16& packageNameToGenerate,
+ const ResourceTablePackage* package,
+ const ResourceTableType* type);
- void generateStyleable(const StringPiece16& packageNameToGenerate,
- const std::u16string& entryName,
- const Styleable* styleable,
- std::ostream* out);
+ void writeStyleableEntryForClass(ClassDefinitionWriter* outClassDef,
+ AnnotationProcessor* processor,
+ const StringPiece16& packageNameToGenerate,
+ const std::u16string& entryName,
+ const Styleable* styleable);
bool skipSymbol(SymbolState state);
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 2dc387b..e9e7881 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -56,13 +56,13 @@
std::string output = out.str();
EXPECT_NE(std::string::npos,
- output.find("public static final int hey_man = 0x01020000;"));
+ output.find("public static final int hey_man=0x01020000;"));
EXPECT_NE(std::string::npos,
- output.find("public static final int[] hey_dude = {"));
+ output.find("public static final int[] hey_dude={"));
EXPECT_NE(std::string::npos,
- output.find("public static final int hey_dude_cool_attr = 0;"));
+ output.find("public static final int hey_dude_cool_attr=0;"));
}
TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
@@ -78,7 +78,7 @@
std::string output = out.str();
EXPECT_NE(std::string::npos, output.find("package com.android.internal;"));
- EXPECT_NE(std::string::npos, output.find("public static final int one = 0x01020000;"));
+ EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
EXPECT_EQ(std::string::npos, output.find("two"));
EXPECT_EQ(std::string::npos, output.find("com_foo$two"));
}
@@ -86,6 +86,7 @@
TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
.setPackageId(u"android", 0x01)
+ .addSimple(u"@android:attr/two", ResourceId(0x01010001))
.addSimple(u"@android:^attr-private/one", ResourceId(0x01010000))
.build();
@@ -116,7 +117,7 @@
std::stringstream out;
ASSERT_TRUE(generator.generate(u"android", &out));
std::string output = out.str();
- EXPECT_NE(std::string::npos, output.find("public static final int one = 0x01020000;"));
+ EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
EXPECT_EQ(std::string::npos, output.find("two"));
EXPECT_EQ(std::string::npos, output.find("three"));
}
@@ -127,8 +128,8 @@
std::stringstream out;
ASSERT_TRUE(generator.generate(u"android", &out));
std::string output = out.str();
- EXPECT_NE(std::string::npos, output.find("public static final int one = 0x01020000;"));
- EXPECT_NE(std::string::npos, output.find("public static final int two = 0x01020001;"));
+ EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
+ EXPECT_NE(std::string::npos, output.find("public static final int two=0x01020001;"));
EXPECT_EQ(std::string::npos, output.find("three"));
}
@@ -138,9 +139,9 @@
std::stringstream out;
ASSERT_TRUE(generator.generate(u"android", &out));
std::string output = out.str();
- EXPECT_NE(std::string::npos, output.find("public static final int one = 0x01020000;"));
- EXPECT_NE(std::string::npos, output.find("public static final int two = 0x01020001;"));
- EXPECT_NE(std::string::npos, output.find("public static final int three = 0x01020002;"));
+ EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
+ EXPECT_NE(std::string::npos, output.find("public static final int two=0x01020001;"));
+ EXPECT_NE(std::string::npos, output.find("public static final int three=0x01020002;"));
}
}
@@ -194,8 +195,8 @@
EXPECT_TRUE(generator.generate(u"android", &out));
std::string output = out.str();
- EXPECT_NE(std::string::npos, output.find("int foo_bar ="));
- EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar ="));
+ EXPECT_NE(std::string::npos, output.find("int foo_bar="));
+ EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar="));
}
TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
@@ -218,7 +219,7 @@
* @deprecated
*/
@Deprecated
- public static final int foo = 0x01010000;)EOF"));
+ public static final int foo=0x01010000;)EOF"));
}
TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
index 901a344..d963d89 100644
--- a/tools/aapt2/java/ManifestClassGenerator.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -18,6 +18,7 @@
#include "XmlDom.h"
#include "java/AnnotationProcessor.h"
+#include "java/ClassDefinitionWriter.h"
#include "java/ManifestClassGenerator.h"
#include "util/Maybe.h"
@@ -58,8 +59,8 @@
return result;
}
-static bool writeSymbol(IDiagnostics* diag, const Source& source, xml::Element* el,
- std::ostream* out) {
+static bool writeSymbol(IDiagnostics* diag, ClassDefinitionWriter* outClassDef, const Source& source,
+ xml::Element* el) {
xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name");
if (!attr) {
diag->error(DiagMessage(source) << "<" << el->name << "> must define 'android:name'");
@@ -72,18 +73,9 @@
return false;
}
- *out << "\n";
-
- if (!util::trimWhitespace(el->comment).empty()) {
- AnnotationProcessor processor(" ");
- processor.appendComment(el->comment);
- *out << processor.buildComment() << "\n";
- std::string annotations = processor.buildAnnotations();
- if (!annotations.empty()) {
- *out << annotations << "\n";
- }
- }
- *out << " public static final String " << result.value() << "=\"" << attr->value << "\";\n";
+ AnnotationProcessor processor;
+ processor.appendComment(el->comment);
+ outClassDef->addStringMember(result.value(), &processor, attr->value);
return true;
}
@@ -100,29 +92,32 @@
}
*out << "package " << package << ";\n\n"
- << "public class Manifest {\n";
+ << "public final class Manifest {\n";
bool error = false;
std::vector<xml::Element*> children = el->getChildElements();
+ ClassDefinitionWriterOptions classOptions;
+ classOptions.useFinalQualifier = true;
+ classOptions.forceCreationIfEmpty = false;
// First write out permissions.
- *out << " public static class permission {\n";
+ ClassDefinitionWriter classDef("permission", classOptions);
for (xml::Element* childEl : children) {
if (childEl->namespaceUri.empty() && childEl->name == u"permission") {
- error |= !writeSymbol(diag, res->file.source, childEl, out);
+ error |= !writeSymbol(diag, &classDef, res->file.source, childEl);
}
}
- *out << " }\n";
+ classDef.writeToStream(out, " ");
// Next write out permission groups.
- *out << " public static class permission_group {\n";
+ classDef = ClassDefinitionWriter("permission_group", classOptions);
for (xml::Element* childEl : children) {
if (childEl->namespaceUri.empty() && childEl->name == u"permission-group") {
- error |= !writeSymbol(diag, res->file.source, childEl, out);
+ error |= !writeSymbol(diag, &classDef, res->file.source, childEl);
}
}
- *out << " }\n";
+ classDef.writeToStream(out, " ");
*out << "}\n";
return !error;
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
index 1b5bc05..4081287 100644
--- a/tools/aapt2/java/ManifestClassGenerator_test.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -39,8 +39,9 @@
std::string actual = out.str();
- const size_t permissionClassPos = actual.find("public static class permission {");
- const size_t permissionGroupClassPos = actual.find("public static class permission_group {");
+ const size_t permissionClassPos = actual.find("public static final class permission {");
+ const size_t permissionGroupClassPos =
+ actual.find("public static final class permission_group {");
ASSERT_NE(std::string::npos, permissionClassPos);
ASSERT_NE(std::string::npos, permissionGroupClassPos);
@@ -113,7 +114,7 @@
* @hide
* @SystemApi
*/
- @android.annotations.SystemApi
+ @android.annotation.SystemApi
public static final String SECRET="android.permission.SECRET";)EOF"));
}
diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp
index 11fcc5d..c7e603e 100644
--- a/tools/aapt2/link/AutoVersioner.cpp
+++ b/tools/aapt2/link/AutoVersioner.cpp
@@ -31,7 +31,7 @@
const int sdkVersionToGenerate) {
assert(sdkVersionToGenerate > config.sdkVersion);
const auto endIter = entry->values.end();
- auto iter = std::lower_bound(entry->values.begin(), endIter, config, cmp::lessThan);
+ auto iter = std::lower_bound(entry->values.begin(), endIter, config, cmp::lessThanConfig);
// The source config came from this list, so it should be here.
assert(iter != entry->values.end());
@@ -124,7 +124,7 @@
auto iter = std::lower_bound(entry->values.begin(),
entry->values.end(),
newConfig,
- cmp::lessThan);
+ cmp::lessThanConfig);
entry->values.insert(
iter,
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 636c2ba..0bcb5ba 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -122,7 +122,7 @@
for (ResourceConfigValue& srcValue : srcEntry->values) {
auto iter = std::lower_bound(dstEntry->values.begin(), dstEntry->values.end(),
- srcValue.config, cmp::lessThan);
+ srcValue.config, cmp::lessThanConfig);
if (iter != dstEntry->values.end() && iter->config == srcValue.config) {
const int collisionResult = ResourceTable::resolveValueCollision(
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 7309396..9a8b263 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -55,7 +55,7 @@
if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
const ConfigDescription kDefaultConfig;
auto iter = std::lower_bound(sr.entry->values.begin(), sr.entry->values.end(),
- kDefaultConfig, cmp::lessThan);
+ kDefaultConfig, cmp::lessThanConfig);
if (iter != sr.entry->values.end() && iter->config == kDefaultConfig) {
// This resource has an Attribute.
diff --git a/tools/aapt2/util/Comparators.h b/tools/aapt2/util/Comparators.h
index 652018e..0ee0bf3 100644
--- a/tools/aapt2/util/Comparators.h
+++ b/tools/aapt2/util/Comparators.h
@@ -17,13 +17,20 @@
#ifndef AAPT_UTIL_COMPARATORS_H
#define AAPT_UTIL_COMPARATORS_H
+#include "ConfigDescription.h"
+#include "ResourceTable.h"
+
namespace aapt {
namespace cmp {
-inline bool lessThan(const ResourceConfigValue& a, const ConfigDescription& b) {
+inline bool lessThanConfig(const ResourceConfigValue& a, const ConfigDescription& b) {
return a.config < b;
}
+inline bool lessThanType(const std::unique_ptr<ResourceTableType>& a, ResourceType b) {
+ return a->type < b;
+}
+
} // namespace cmp
} // namespace aapt
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 7ee06f3..3c260a8 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -241,6 +241,13 @@
}
@Override
+ public void overridePendingAppTransitionMultiThumbFuture(
+ IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback startedCallback,
+ boolean scaleUp) throws RemoteException {
+
+ }
+
+ @Override
public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
IRemoteCallback callback0, IRemoteCallback callback1, boolean scaleUp) {
// TODO Auto-generated method stub
@@ -515,10 +522,23 @@
}
@Override
+ public int getDockedStackSide() throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public void setDockedStackResizing(boolean resizing) throws RemoteException {
+ }
+
+ @Override
public void cancelTaskWindowTransition(int taskId) {
}
@Override
+ public void cancelTaskThumbnailTransition(int taskId) {
+ }
+
+ @Override
public void endProlongedAnimations() {
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index c2d8d0c..3662573 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -48,7 +48,7 @@
@Override
public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6,
- boolean b, Configuration configuration) throws RemoteException {
+ boolean b, Configuration configuration, Rect rect7) throws RemoteException {
// pass for now.
}