Merge "Prevent early recent trimming of distinct documents."
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4449e4f..65c63f6 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2611,14 +2611,6 @@
return true;
}
- case UPDATE_DEVICE_OWNER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- String packageName = data.readString();
- updateDeviceOwner(packageName);
- reply.writeNoException();
- return true;
- }
-
case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String pkg = data.readString();
@@ -6163,18 +6155,6 @@
}
@Override
- public void updateDeviceOwner(String packageName) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeString(packageName);
- mRemote.transact(UPDATE_DEVICE_OWNER_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- @Override
public int getPackageProcessState(String packageName, String callingPackage)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index b69a480..cf2452b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -518,7 +518,6 @@
public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
throws RemoteException;
public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
- public void updateDeviceOwner(String packageName) throws RemoteException;
public int getPackageProcessState(String packageName, String callingPackage)
throws RemoteException;
@@ -881,7 +880,6 @@
int NOTE_ALARM_FINISH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+292;
int GET_PACKAGE_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+293;
int SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+294;
- int UPDATE_DEVICE_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+295;
int KEYGUARD_GOING_AWAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296;
int REGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+297;
int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 8b7abb7..891558f 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -275,7 +275,7 @@
if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
final String isa = VMRuntime.getRuntime().vmInstructionSet();
try {
- ActivityThread.getPackageManager().performDexOptIfNeeded(mPackageName, isa);
+ ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
} catch (RemoteException re) {
// Ignored.
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ba84642..b89c5a6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -149,7 +149,25 @@
/**
* @hide
- * TODO Add Documentation
+ * Activity action: Starts the provisioning flow which sets up a managed user.
+ *
+ * <p>This intent will typically be sent by a mobile device management application (MDM).
+ * Provisioning configures the current user as managed user and sets the MDM as the profile
+ * owner who has full control over the user. Provisioning can only happen before user setup has
+ * been completed. Use {@link #isProvisioningAllowed(String)} to check if provisioning is
+ * allowed.
+ *
+ * This intent should contain the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME},
+ * although specifying only {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is also
+ * supported.
+ *
+ * <p> If provisioning fails, the device returns to its previous state.
+ *
+ * <p>If launched with {@link android.app.Activity#startActivityForResult(Intent, int)} a
+ * result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part of
+ * the provisioning flow was successful, although this doesn't guarantee the full flow will
+ * succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} implies
+ * that the user backed-out of provisioning, or some precondition for provisioning wasn't met.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROVISION_MANAGED_USER
@@ -577,7 +595,7 @@
* extra field. This will invoke a UI to bring the user through adding the profile owner admin
* to remotely control restrictions on the user.
*
- * <p>The intent must be invoked via {@link Activity#startActivityForResult()} to receive the
+ * <p>The intent must be invoked via {@link Activity#startActivityForResult} to receive the
* result of whether or not the user approved the action. If approved, the result will
* be {@link Activity#RESULT_OK} and the component will be set as an active admin as well
* as a profile owner.
@@ -2978,7 +2996,7 @@
/**
* @hide
- * @param user The user for whom to fetch the profile owner name, if any.
+ * @param userId The user for whom to fetch the profile owner name, if any.
* @return the human readable name of the organisation associated with this profile owner or
* null if one is not set.
* @throws IllegalArgumentException if the userId is invalid.
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 4270e16..5a46cd5 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -80,4 +80,10 @@
* This method always returns a new {@link Bundle}.
*/
public abstract Bundle getComposedUserRestrictions(int userId, Bundle inBundle);
+
+ /**
+ * @return true if a package is a device admin (possibly DO or PO) running on
+ * user {@code userId}.
+ */
+ public abstract boolean isDeviceAdminPackage(int userId, String packageName);
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index fec2c44..6fe1efd 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -420,10 +420,14 @@
boolean hasSystemUidErrors();
/**
- * Ask the package manager to perform boot-time dex-opt of all
- * existing packages.
+ * Ask the package manager to fstrim the disk if needed.
*/
- void performBootDexOpt();
+ void performFstrimIfNeeded();
+
+ /**
+ * Notify the package manager that a package is going to be used.
+ */
+ void notifyPackageUse(String packageName);
/**
* Ask the package manager to perform dex-opt (if needed) on the given
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 37f2c04..9034cc9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6285,7 +6285,10 @@
public static final String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
/**
- * Whether the device has been provisioned (0 = false, 1 = true)
+ * Whether the device has been provisioned (0 = false, 1 = true).
+ * <p>On a multiuser device with a separate system user, the screen may be locked
+ * as soon as this is set to true and further activities cannot be launched on the
+ * system user unless they are marked to show over keyguard.
*/
public static final String DEVICE_PROVISIONED = "device_provisioned";
diff --git a/core/java/android/security/net/config/ApplicationConfig.java b/core/java/android/security/net/config/ApplicationConfig.java
index 9bf344a..b627641 100644
--- a/core/java/android/security/net/config/ApplicationConfig.java
+++ b/core/java/android/security/net/config/ApplicationConfig.java
@@ -30,6 +30,9 @@
* @hide
*/
public final class ApplicationConfig {
+ private static ApplicationConfig sInstance;
+ private static Object sLock = new Object();
+
private Set<Pair<Domain, NetworkSecurityConfig>> mConfigs;
private NetworkSecurityConfig mDefaultConfig;
private X509TrustManager mTrustManager;
@@ -129,4 +132,16 @@
mInitialized = true;
}
}
+
+ public static void setDefaultInstance(ApplicationConfig config) {
+ synchronized (sLock) {
+ sInstance = config;
+ }
+ }
+
+ public static ApplicationConfig getDefaultInstance() {
+ synchronized (sLock) {
+ return sInstance;
+ }
+ }
}
diff --git a/core/java/android/security/net/config/KeyStoreCertificateSource.java b/core/java/android/security/net/config/KeyStoreCertificateSource.java
new file mode 100644
index 0000000..1973ef1
--- /dev/null
+++ b/core/java/android/security/net/config/KeyStoreCertificateSource.java
@@ -0,0 +1,65 @@
+/*
+ * 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 android.security.net.config;
+
+import android.util.ArraySet;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Set;
+
+/**
+ * {@link CertificateSource} which provides certificates from trusted certificate entries of a
+ * {@link KeyStore}.
+ */
+class KeyStoreCertificateSource implements CertificateSource {
+ private final Object mLock = new Object();
+ private final KeyStore mKeyStore;
+ private Set<X509Certificate> mCertificates;
+
+ public KeyStoreCertificateSource(KeyStore ks) {
+ mKeyStore = ks;
+ }
+
+ @Override
+ public Set<X509Certificate> getCertificates() {
+ synchronized (mLock) {
+ if (mCertificates != null) {
+ return mCertificates;
+ }
+ try {
+ Set<X509Certificate> certificates = new ArraySet<>(mKeyStore.size());
+ for (Enumeration<String> en = mKeyStore.aliases(); en.hasMoreElements();) {
+ String alias = en.nextElement();
+ if (!mKeyStore.isCertificateEntry(alias)) {
+ continue;
+ }
+ X509Certificate cert = (X509Certificate) mKeyStore.getCertificate(alias);
+ if (cert != null) {
+ certificates.add(cert);
+ }
+ }
+ mCertificates = certificates;
+ return mCertificates;
+ } catch (KeyStoreException e) {
+ throw new RuntimeException("Failed to load certificates from KeyStore", e);
+ }
+ }
+ }
+}
diff --git a/core/java/android/security/net/config/KeyStoreConfigSource.java b/core/java/android/security/net/config/KeyStoreConfigSource.java
new file mode 100644
index 0000000..8d4f098
--- /dev/null
+++ b/core/java/android/security/net/config/KeyStoreConfigSource.java
@@ -0,0 +1,49 @@
+/*
+ * 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 android.security.net.config;
+
+import android.util.Pair;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.util.Set;
+
+/**
+ * {@link ConfigSource} with a single default config based on a {@link KeyStore} and no per domain
+ * configs.
+ */
+class KeyStoreConfigSource implements ConfigSource {
+ private final NetworkSecurityConfig mConfig;
+
+ public KeyStoreConfigSource(KeyStore ks) {
+ mConfig = new NetworkSecurityConfig.Builder()
+ .addCertificatesEntryRef(
+ // Use the KeyStore and do not override pins (of which there are none).
+ new CertificatesEntryRef(new KeyStoreCertificateSource(ks), false))
+ .build();
+ }
+
+ @Override
+ public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() {
+ return null;
+ }
+
+ @Override
+ public NetworkSecurityConfig getDefaultConfig() {
+ return mConfig;
+ }
+}
+
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index 1c787b4..503854e 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -227,10 +227,14 @@
return Collections.<CertificatesEntryRef>emptyList();
}
- public boolean hasCertificateEntryRefs() {
+ public boolean hasCertificatesEntryRefs() {
return mCertificatesEntryRefs != null;
}
+ List<CertificatesEntryRef> getCertificatesEntryRefs() {
+ return mCertificatesEntryRefs;
+ }
+
public NetworkSecurityConfig build() {
boolean cleartextPermitted = getEffectiveCleartextTrafficPermitted();
boolean hstsEnforced = getEffectiveHstsEnforced();
diff --git a/core/java/android/security/net/config/NetworkSecurityConfigProvider.java b/core/java/android/security/net/config/NetworkSecurityConfigProvider.java
new file mode 100644
index 0000000..ca8cdae
--- /dev/null
+++ b/core/java/android/security/net/config/NetworkSecurityConfigProvider.java
@@ -0,0 +1,33 @@
+/*
+ * 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 android.security.net.config;
+
+import java.security.Provider;
+
+/** @hide */
+public final class NetworkSecurityConfigProvider extends Provider {
+
+ private static String PREFIX =
+ NetworkSecurityConfigProvider.class.getPackage().getName() + ".";
+
+ public NetworkSecurityConfigProvider() {
+ // TODO: More clever name than this
+ super("AndroidNSSP", 1.0, "Android Network Security Policy Provider");
+ put("TrustManagerFactory.PKIX", PREFIX + "RootTrustManagerFactorySpi");
+ put("Alg.Alias.TrustManagerFactory.X509", "PKIX");
+ }
+}
diff --git a/core/java/android/security/net/config/RootTrustManagerFactorySpi.java b/core/java/android/security/net/config/RootTrustManagerFactorySpi.java
new file mode 100644
index 0000000..0a1fe88
--- /dev/null
+++ b/core/java/android/security/net/config/RootTrustManagerFactorySpi.java
@@ -0,0 +1,75 @@
+/*
+ * 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 android.security.net.config;
+
+import android.util.Pair;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Set;
+import javax.net.ssl.ManagerFactoryParameters;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.TrustManagerFactorySpi;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/** @hide */
+public class RootTrustManagerFactorySpi extends TrustManagerFactorySpi {
+ private ApplicationConfig mApplicationConfig;
+ private NetworkSecurityConfig mConfig;
+
+ @Override
+ public void engineInit(ManagerFactoryParameters spec)
+ throws InvalidAlgorithmParameterException {
+ if (!(spec instanceof ApplicationConfigParameters)) {
+ throw new InvalidAlgorithmParameterException("Unsupported spec: " + spec + ". Only "
+ + ApplicationConfigParameters.class.getName() + " supported");
+
+ }
+ mApplicationConfig = ((ApplicationConfigParameters) spec).config;
+ }
+
+ @Override
+ public void engineInit(KeyStore ks) throws KeyStoreException {
+ if (ks != null) {
+ mApplicationConfig = new ApplicationConfig(new KeyStoreConfigSource(ks));
+ } else {
+ mApplicationConfig = ApplicationConfig.getDefaultInstance();
+ }
+ }
+
+ @Override
+ public TrustManager[] engineGetTrustManagers() {
+ if (mApplicationConfig == null) {
+ throw new IllegalStateException("TrustManagerFactory not initialized");
+ }
+ return new TrustManager[] { mApplicationConfig.getTrustManager() };
+ }
+
+ @VisibleForTesting
+ public static final class ApplicationConfigParameters implements ManagerFactoryParameters {
+ public final ApplicationConfig config;
+ public ApplicationConfigParameters(ApplicationConfig config) {
+ this.config = config;
+ }
+ }
+}
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index 6abfb66..1706e95 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -27,8 +27,13 @@
* @hide
*/
public class XmlConfigSource implements ConfigSource {
+ private static final int CONFIG_BASE = 0;
+ private static final int CONFIG_DOMAIN = 1;
+ private static final int CONFIG_DEBUG = 2;
+
private final Object mLock = new Object();
private final int mResourceId;
+ private final boolean mDebugBuild;
private boolean mInitialized;
private NetworkSecurityConfig mDefaultConfig;
@@ -36,8 +41,13 @@
private Context mContext;
public XmlConfigSource(Context context, int resourceId) {
+ this(context, resourceId, false);
+ }
+
+ public XmlConfigSource(Context context, int resourceId, boolean debugBuild) {
mResourceId = resourceId;
mContext = context;
+ mDebugBuild = debugBuild;
}
public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() {
@@ -50,6 +60,19 @@
return mDefaultConfig;
}
+ private static final String getConfigString(int configType) {
+ switch (configType) {
+ case CONFIG_BASE:
+ return "base-config";
+ case CONFIG_DOMAIN:
+ return "domain-config";
+ case CONFIG_DEBUG:
+ return "debug-overrides";
+ default:
+ throw new IllegalArgumentException("Unknown config type: " + configType);
+ }
+ }
+
private void ensureInitialized() {
synchronized (mLock) {
if (mInitialized) {
@@ -147,9 +170,11 @@
return new Domain(domain, includeSubdomains);
}
- private CertificatesEntryRef parseCertificatesEntry(XmlResourceParser parser)
+ private CertificatesEntryRef parseCertificatesEntry(XmlResourceParser parser,
+ boolean defaultOverridePins)
throws IOException, XmlPullParserException, ParserException {
- boolean overridePins = parser.getAttributeBooleanValue(null, "overridePins", false);
+ boolean overridePins =
+ parser.getAttributeBooleanValue(null, "overridePins", defaultOverridePins);
int sourceId = parser.getAttributeResourceValue(null, "src", -1);
String sourceString = parser.getAttributeValue(null, "src");
CertificateSource source = null;
@@ -171,14 +196,15 @@
return new CertificatesEntryRef(source, overridePins);
}
- private Collection<CertificatesEntryRef> parseTrustAnchors(XmlResourceParser parser)
+ private Collection<CertificatesEntryRef> parseTrustAnchors(XmlResourceParser parser,
+ boolean defaultOverridePins)
throws IOException, XmlPullParserException, ParserException {
int outerDepth = parser.getDepth();
List<CertificatesEntryRef> anchors = new ArrayList<>();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
String tagName = parser.getName();
if (tagName.equals("certificates")) {
- anchors.add(parseCertificatesEntry(parser));
+ anchors.add(parseCertificatesEntry(parser, defaultOverridePins));
} else {
XmlUtils.skipCurrentTag(parser);
}
@@ -188,7 +214,7 @@
private List<Pair<NetworkSecurityConfig.Builder, Set<Domain>>> parseConfigEntry(
XmlResourceParser parser, Set<String> seenDomains,
- NetworkSecurityConfig.Builder parentBuilder, boolean baseConfig)
+ NetworkSecurityConfig.Builder parentBuilder, int configType)
throws IOException, XmlPullParserException, ParserException {
List<Pair<NetworkSecurityConfig.Builder, Set<Domain>>> builders = new ArrayList<>();
NetworkSecurityConfig.Builder builder = new NetworkSecurityConfig.Builder();
@@ -196,6 +222,7 @@
Set<Domain> domains = new ArraySet<>();
boolean seenPinSet = false;
boolean seenTrustAnchors = false;
+ boolean defaultOverridePins = configType == CONFIG_DEBUG;
String configName = parser.getName();
int outerDepth = parser.getDepth();
// Add this builder now so that this builder occurs before any of its children. This
@@ -219,8 +246,9 @@
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
String tagName = parser.getName();
if ("domain".equals(tagName)) {
- if (baseConfig) {
- throw new ParserException(parser, "domain element not allowed in base-config");
+ if (configType != CONFIG_DOMAIN) {
+ throw new ParserException(parser,
+ "domain element not allowed in " + getConfigString(configType));
}
Domain domain = parseDomain(parser, seenDomains);
domains.add(domain);
@@ -229,12 +257,13 @@
throw new ParserException(parser,
"Multiple trust-anchor elements not allowed");
}
- builder.addCertificatesEntryRefs(parseTrustAnchors(parser));
+ builder.addCertificatesEntryRefs(
+ parseTrustAnchors(parser, defaultOverridePins));
seenTrustAnchors = true;
} else if ("pin-set".equals(tagName)) {
- if (baseConfig) {
+ if (configType != CONFIG_DOMAIN) {
throw new ParserException(parser,
- "pin-set element not allowed in base-config");
+ "pin-set element not allowed in " + getConfigString(configType));
}
if (seenPinSet) {
throw new ParserException(parser, "Multiple pin-set elements not allowed");
@@ -242,41 +271,68 @@
builder.setPinSet(parsePinSet(parser));
seenPinSet = true;
} else if ("domain-config".equals(tagName)) {
- if (baseConfig) {
+ if (configType != CONFIG_DOMAIN) {
throw new ParserException(parser,
- "Nested domain-config not allowed in base-config");
+ "Nested domain-config not allowed in " + getConfigString(configType));
}
- builders.addAll(parseConfigEntry(parser, seenDomains, builder, false));
+ builders.addAll(parseConfigEntry(parser, seenDomains, builder, configType));
} else {
XmlUtils.skipCurrentTag(parser);
}
}
- if (!baseConfig && domains.isEmpty()) {
+ if (configType == CONFIG_DOMAIN && domains.isEmpty()) {
throw new ParserException(parser, "No domain elements in domain-config");
}
return builders;
}
+ private void addDebugAnchorsIfNeeded(NetworkSecurityConfig.Builder debugConfigBuilder,
+ NetworkSecurityConfig.Builder builder) {
+ if (debugConfigBuilder == null || !debugConfigBuilder.hasCertificatesEntryRefs()) {
+ return;
+ }
+ // Don't add trust anchors if not already present, the builder will inherit the anchors
+ // from its parent, and that's where the trust anchors should be added.
+ if (!builder.hasCertificatesEntryRefs()) {
+ return;
+ }
+
+ builder.addCertificatesEntryRefs(debugConfigBuilder.getCertificatesEntryRefs());
+ }
+
private void parseNetworkSecurityConfig(XmlResourceParser parser)
throws IOException, XmlPullParserException, ParserException {
Set<String> seenDomains = new ArraySet<>();
List<Pair<NetworkSecurityConfig.Builder, Set<Domain>>> builders = new ArrayList<>();
NetworkSecurityConfig.Builder baseConfigBuilder = null;
+ NetworkSecurityConfig.Builder debugConfigBuilder = null;
boolean seenDebugOverrides = false;
boolean seenBaseConfig = false;
XmlUtils.beginDocument(parser, "network-security-config");
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
- // TODO: support debug-override.
if ("base-config".equals(parser.getName())) {
if (seenBaseConfig) {
throw new ParserException(parser, "Only one base-config allowed");
}
seenBaseConfig = true;
- baseConfigBuilder = parseConfigEntry(parser, seenDomains, null, true).get(0).first;
+ baseConfigBuilder =
+ parseConfigEntry(parser, seenDomains, null, CONFIG_BASE).get(0).first;
} else if ("domain-config".equals(parser.getName())) {
- builders.addAll(parseConfigEntry(parser, seenDomains, baseConfigBuilder, false));
+ builders.addAll(
+ parseConfigEntry(parser, seenDomains, baseConfigBuilder, CONFIG_DOMAIN));
+ } else if ("debug-overrides".equals(parser.getName())) {
+ if (seenDebugOverrides) {
+ throw new ParserException(parser, "Only one debug-overrides allowed");
+ }
+ if (mDebugBuild) {
+ debugConfigBuilder =
+ parseConfigEntry(parser, seenDomains, null, CONFIG_DEBUG).get(0).first;
+ } else {
+ XmlUtils.skipCurrentTag(parser);
+ }
+ seenDebugOverrides = true;
} else {
XmlUtils.skipCurrentTag(parser);
}
@@ -286,8 +342,10 @@
// there. If there is no base config use the platform default.
NetworkSecurityConfig.Builder platformDefaultBuilder =
NetworkSecurityConfig.getDefaultBuilder();
+ addDebugAnchorsIfNeeded(debugConfigBuilder, platformDefaultBuilder);
if (baseConfigBuilder != null) {
baseConfigBuilder.setParent(platformDefaultBuilder);
+ addDebugAnchorsIfNeeded(debugConfigBuilder, baseConfigBuilder);
} else {
baseConfigBuilder = platformDefaultBuilder;
}
@@ -306,6 +364,7 @@
if (builder.getParent() == null) {
builder.setParent(baseConfigBuilder);
}
+ addDebugAnchorsIfNeeded(debugConfigBuilder, builder);
NetworkSecurityConfig config = builder.build();
for (Domain domain : domains) {
configs.add(new Pair<>(domain, config));
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index c2c247e..d563f51 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -17,6 +17,9 @@
package android.view;
import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import java.util.ArrayList;
import java.util.Collections;
@@ -173,6 +176,7 @@
// Note: This sort is stable.
mSequentialFocusComparator.setRoot(root);
mSequentialFocusComparator.setIsLayoutRtl(root.isLayoutRtl());
+ mSequentialFocusComparator.setFocusables(focusables);
Collections.sort(focusables, mSequentialFocusComparator);
} finally {
mSequentialFocusComparator.recycle();
@@ -598,8 +602,16 @@
+ "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
}
+ private static final boolean isValidId(final int id) {
+ return id != 0 && id != View.NO_ID;
+ }
+
/**
* Sorts views according to their visual layout and geometry for default tab order.
+ * If views are part of a focus chain (nextFocusForwardId), then they are all grouped
+ * together. The head of the chain is used to determine the order of the chain and is
+ * first in the order and the tail of the chain is the last in the order. The views
+ * in the middle of the chain can be arbitrary order.
* This is used for sequential focus traversal.
*/
private static final class SequentialFocusComparator implements Comparator<View> {
@@ -607,9 +619,15 @@
private final Rect mSecondRect = new Rect();
private ViewGroup mRoot;
private boolean mIsLayoutRtl;
+ private final SparseArray<View> mFocusables = new SparseArray<View>();
+ private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
+ private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
public void recycle() {
mRoot = null;
+ mFocusables.clear();
+ mHeadsOfChains.clear();
+ mIsConnectedTo.clear();
}
public void setRoot(ViewGroup root) {
@@ -620,11 +638,72 @@
mIsLayoutRtl = b;
}
+ public void setFocusables(ArrayList<View> focusables) {
+ for (int i = focusables.size() - 1; i >= 0; i--) {
+ final View view = focusables.get(i);
+ final int id = view.getId();
+ if (isValidId(id)) {
+ mFocusables.put(id, view);
+ }
+ final int nextId = view.getNextFocusForwardId();
+ if (isValidId(nextId)) {
+ mIsConnectedTo.put(nextId, true);
+ }
+ }
+
+ for (int i = focusables.size() - 1; i >= 0; i--) {
+ final View view = focusables.get(i);
+ final int nextId = view.getNextFocusForwardId();
+ if (isValidId(nextId) && !mIsConnectedTo.get(view.getId())) {
+ setHeadOfChain(view);
+ }
+ }
+ }
+
+ private void setHeadOfChain(View head) {
+ for (View view = head; view != null;
+ view = mFocusables.get(view.getNextFocusForwardId())) {
+ final View otherHead = mHeadsOfChains.get(view);
+ if (otherHead != null) {
+ if (otherHead == head) {
+ return; // This view has already had its head set properly
+ }
+ // A hydra -- multi-headed focus chain (e.g. A->C and B->C)
+ // Use the one we've already chosen instead and reset this chain.
+ view = head;
+ head = otherHead;
+ }
+ mHeadsOfChains.put(view, head);
+ }
+ }
+
public int compare(View first, View second) {
if (first == second) {
return 0;
}
+ // Order between views within a chain is immaterial -- next/previous is
+ // within a chain is handled elsewhere.
+ View firstHead = mHeadsOfChains.get(first);
+ View secondHead = mHeadsOfChains.get(second);
+ if (firstHead == secondHead && firstHead != null) {
+ if (first == firstHead) {
+ return -1; // first is the head, it should be first
+ } else if (second == firstHead) {
+ return 1; // second is the head, it should be first
+ } else if (isValidId(first.getNextFocusForwardId())) {
+ return -1; // first is not the end of the chain
+ } else {
+ return 1; // first is end of chain
+ }
+ }
+ if (firstHead != null) {
+ first = firstHead;
+ }
+ if (secondHead != null) {
+ second = secondHead;
+ }
+ // First see if they belong to the same focus chain.
getRect(first, mFirstRect);
getRect(second, mSecondRect);
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 1be2f95..3fc70cc 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -101,16 +101,24 @@
* for the parent window appears. This allows for synchronizing movement of a child
* to repainting the contents of the parent.
*
+ * "width" and "height" correspond to the width and height members of
+ * WindowManager.LayoutParams in the {@link #relayout relayout()} case.
+ * This may differ from the surface buffer size in the
+ * case of {@link LayoutParams#FLAG_SCALED} and {@link #relayout relayout()}
+ * must be used with requestedWidth/height if this must be changed.
+ *
* @param window The window being modified. Must be attached to a parent window
* or this call will fail.
* @param x The new x position
* @param y The new y position
+ * @param width The new width
+ * @param height The new height
* @param deferTransactionUntilFrame Frame number from our parent (attached) to
* defer this action until.
* @param outFrame Rect in which is placed the new position/size on screen.
*/
- void repositionChild(IWindow childWindow, int x, int y, long deferTransactionUntilFrame,
- out Rect outFrame);
+ void repositionChild(IWindow childWindow, int left, int top, int right, int bottom,
+ long deferTransactionUntilFrame, out Rect outFrame);
/**
* If a call to relayout() asked to have the surface destroy deferred,
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 514f88b..589c0dc 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -157,10 +157,10 @@
long mLastLockTime = 0;
boolean mVisible = false;
- int mLeft = -1;
- int mTop = -1;
- int mWidth = -1;
- int mHeight = -1;
+ int mWindowSpaceLeft = -1;
+ int mWindowSpaceTop = -1;
+ int mWindowSpaceWidth = -1;
+ int mWindowSpaceHeight = -1;
int mFormat = -1;
final Rect mSurfaceFrame = new Rect();
int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
@@ -445,32 +445,33 @@
getLocationInWindow(mLocation);
final boolean creating = mWindow == null;
final boolean formatChanged = mFormat != mRequestedFormat;
- final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
+ final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight;
final boolean visibleChanged = mVisible != mRequestedVisible;
- final boolean layoutSizeChanged = getWidth() != mLayout.width || getHeight() != mLayout.height;
- final boolean positionChanged = mLeft != mLocation[0] || mTop != mLocation[1];
+ final boolean layoutSizeChanged = getWidth() != mLayout.width
+ || getHeight() != mLayout.height;
+ final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1];
if (force || creating || formatChanged || sizeChanged || visibleChanged
- || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded || layoutSizeChanged) {
+ || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
+ " format=" + formatChanged + " size=" + sizeChanged
+ " visible=" + visibleChanged
- + " left=" + (mLeft != mLocation[0])
- + " top=" + (mTop != mLocation[1]));
+ + " left=" + (mWindowSpaceLeft != mLocation[0])
+ + " top=" + (mWindowSpaceTop != mLocation[1]));
try {
final boolean visible = mVisible = mRequestedVisible;
- mLeft = mLocation[0];
- mTop = mLocation[1];
- mWidth = myWidth;
- mHeight = myHeight;
+ mWindowSpaceLeft = mLocation[0];
+ mWindowSpaceTop = mLocation[1];
+ mWindowSpaceWidth = myWidth;
+ mWindowSpaceHeight = myHeight;
mFormat = mRequestedFormat;
// Scaling/Translate window's layout here because mLayout is not used elsewhere.
// Places the window relative
- mLayout.x = mLeft;
- mLayout.y = mTop;
+ mLayout.x = mWindowSpaceLeft;
+ mLayout.y = mWindowSpaceTop;
mLayout.width = getWidth();
mLayout.height = getHeight();
if (mTranslator != null) {
@@ -485,6 +486,14 @@
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
;
+ if (!creating && !force && !mUpdateWindowNeeded) {
+ mLayout.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
+ } else {
+ mLayout.privateFlags &=
+ ~WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
+ }
+
if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
mLayout.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
@@ -516,7 +525,7 @@
if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
relayoutResult = mSession.relayout(
- mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
+ mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight,
visible ? VISIBLE : GONE,
WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
mWinFrame, mOverscanInsets, mContentInsets,
@@ -621,11 +630,19 @@
TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
" w=" + mLayout.width + " h=" + mLayout.height +
", frame=" + mSurfaceFrame);
- } else if (positionChanged) { // Only the position has changed
- mLeft = mLocation[0];
- mTop = mLocation[1];
+ } else if (positionChanged || layoutSizeChanged) { // Only the position has changed
+ mWindowSpaceLeft = mLocation[0];
+ mWindowSpaceTop = mLocation[1];
+ // For our size changed check, we keep mLayout.width and mLayout.height
+ // in view local space.
+ mLocation[0] = mLayout.width = getWidth();
+ mLocation[1] = mLayout.height = getHeight();
+
+ transformFromViewToWindowSpace(mLocation);
+
try {
- mSession.repositionChild(mWindow, mLeft, mTop,
+ mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
+ mLocation[0], mLocation[1],
viewRoot != null ? viewRoot.getNextFrameNumber() : -1,
mWinFrame);
} catch (RemoteException ex) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c2af9f7..66b05a2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -18498,21 +18498,29 @@
* must be an array of two integers. After the method returns, the array
* contains the x and y location in that order.</p>
*
- * @param location an array of two integers in which to hold the coordinates
+ * @param outWindowSpace an array of two integers in which to hold the coordinates
*/
- public void getLocationInWindow(@Size(2) int[] location) {
- if (location == null || location.length < 2) {
- throw new IllegalArgumentException("location must be an array of two integers");
+ public void getLocationInWindow(@Size(2) int[] outWindowSpace) {
+ outWindowSpace[0] = 0;
+ outWindowSpace[1] = 0;
+
+ transformFromViewToWindowSpace(outWindowSpace);
+ }
+
+ void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
+ if (inOutLocation == null || inOutLocation.length < 2) {
+ throw new IllegalArgumentException("inOutLocation must be an array of two integers");
}
if (mAttachInfo == null) {
// When the view is not attached to a window, this method does not make sense
- location[0] = location[1] = 0;
+ inOutLocation[0] = inOutLocation[1] = 0;
return;
}
- float[] position = mAttachInfo.mTmpTransformLocation;
- position[0] = position[1] = 0.0f;
+ float position[] = mAttachInfo.mTmpTransformLocation;
+ position[0] = inOutLocation[0];
+ position[1] = inOutLocation[1];
if (!hasIdentityMatrix()) {
getMatrix().mapPoints(position);
@@ -18544,8 +18552,8 @@
position[1] -= vr.mCurScrollY;
}
- location[0] = (int) (position[0] + 0.5f);
- location[1] = (int) (position[1] + 0.5f);
+ inOutLocation[0] = (int) (position[0] + 0.5f);
+ inOutLocation[1] = (int) (position[1] + 0.5f);
}
/**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 2d0435f..edf4297 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1148,6 +1148,16 @@
public static final int PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT = 0x00001000;
/**
+ * Flag indicating that the x, y, width, and height members should be
+ * ignored (and thus their previous value preserved). For example
+ * because they are being managed externally through repositionChild.
+ *
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_PRESERVE_GEOMETRY = 0x00002000;
+
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 7e542c9..cbb6109 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -171,7 +171,7 @@
// Set up year picker view.
mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
mYearPickerView.setRange(mMinDate, mMaxDate);
- mYearPickerView.setDate(mCurrentDate.getTimeInMillis());
+ mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR));
mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
// Set up content descriptions.
@@ -267,6 +267,9 @@
// Automatically switch to day picker.
setCurrentView(VIEW_MONTH_DAY);
+
+ // Switch focus back to the year text.
+ mHeaderYear.requestFocus();
}
};
@@ -344,7 +347,18 @@
mAnimator.announceForAccessibility(mSelectDay);
break;
case VIEW_YEAR:
- mYearPickerView.setDate(mCurrentDate.getTimeInMillis());
+ final int year = mCurrentDate.get(Calendar.YEAR);
+ mYearPickerView.setYear(year);
+ mYearPickerView.post(new Runnable() {
+ @Override
+ public void run() {
+ mYearPickerView.requestFocus();
+ final View selected = mYearPickerView.getSelectedView();
+ if (selected != null) {
+ selected.requestFocus();
+ }
+ }
+ });
if (mCurrentView != viewIndex) {
mHeaderMonthDay.setActivated(false);
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 8fe8252..f5840dc 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -287,6 +287,14 @@
return null;
}
+ SimpleMonthView getView(Object object) {
+ if (object == null) {
+ return null;
+ }
+ final ViewHolder holder = (ViewHolder) object;
+ return holder.calendar;
+ }
+
private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
@Override
public void onDayClick(SimpleMonthView view, Calendar day) {
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index bb6e3a4..5f0ae29 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -16,12 +16,18 @@
package android.widget;
-import com.android.internal.widget.ViewPager;
-
+import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+
+import com.android.internal.util.Predicate;
+import com.android.internal.widget.PagerAdapter;
+import com.android.internal.widget.ViewPager;
import java.util.ArrayList;
@@ -134,4 +140,37 @@
mMatchParentChildren.clear();
}
+
+ @Override
+ protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ if (predicate.apply(this)) {
+ return this;
+ }
+
+ // Always try the selected view first.
+ final DayPickerPagerAdapter adapter = (DayPickerPagerAdapter) getAdapter();
+ final SimpleMonthView current = adapter.getView(getCurrent());
+ if (current != childToSkip && current != null) {
+ final View v = current.findViewByPredicate(predicate);
+ if (v != null) {
+ return v;
+ }
+ }
+
+ final int len = getChildCount();
+ for (int i = 0; i < len; i++) {
+ final View child = getChildAt(i);
+
+ if (child != childToSkip && child != current) {
+ final View v = child.findViewByPredicate(predicate);
+
+ if (v != null) {
+ return v;
+ }
+ }
+ }
+
+ return null;
+ }
+
}
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index d21a5f7..e31bbe9 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -128,6 +128,15 @@
/** @hide */
@Override
+ public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfoInternal(info);
+ if (isEnabled()) {
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT);
+ }
+ }
+
+ /** @hide */
+ @Override
public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
switch (action) {
case AccessibilityNodeInfo.ACTION_SET_TEXT: {
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index e9325ef..6edce91 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -34,8 +35,10 @@
import android.util.IntArray;
import android.util.MathUtils;
import android.util.StateSet;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -61,11 +64,14 @@
private static final String DEFAULT_TITLE_FORMAT = "MMMMy";
private static final String DAY_OF_WEEK_FORMAT = "EEEEE";
+ private static final int SELECTED_HIGHLIGHT_ALPHA = 0xB0;
+
private final TextPaint mMonthPaint = new TextPaint();
private final TextPaint mDayOfWeekPaint = new TextPaint();
private final TextPaint mDayPaint = new TextPaint();
private final Paint mDaySelectorPaint = new Paint();
private final Paint mDayHighlightPaint = new Paint();
+ private final Paint mDayHighlightSelectorPaint = new Paint();
private final Calendar mCalendar = Calendar.getInstance();
private final Calendar mDayOfWeekLabelCalendar = Calendar.getInstance();
@@ -130,7 +136,9 @@
private ColorStateList mDayTextColor;
- private int mTouchedItem = -1;
+ private int mHighlightedDay = -1;
+ private int mPreviouslyHighlightedDay = -1;
+ private boolean mIsTouchHighlighted = false;
public SimpleMonthView(Context context) {
this(context, null);
@@ -268,6 +276,9 @@
mDayHighlightPaint.setAntiAlias(true);
mDayHighlightPaint.setStyle(Style.FILL);
+ mDayHighlightSelectorPaint.setAntiAlias(true);
+ mDayHighlightSelectorPaint.setStyle(Style.FILL);
+
mDayPaint.setAntiAlias(true);
mDayPaint.setTextSize(dayTextSize);
mDayPaint.setTypeface(Typeface.create(dayTypeface, 0));
@@ -296,6 +307,8 @@
final int activatedColor = dayBackgroundColor.getColorForState(
StateSet.get(StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED), 0);
mDaySelectorPaint.setColor(activatedColor);
+ mDayHighlightSelectorPaint.setColor(activatedColor);
+ mDayHighlightSelectorPaint.setAlpha(SELECTED_HIGHLIGHT_ALPHA);
invalidate();
}
@@ -326,8 +339,10 @@
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
final int touchedItem = getDayAtLocation(x, y);
- if (mTouchedItem != touchedItem) {
- mTouchedItem = touchedItem;
+ mIsTouchHighlighted = true;
+ if (mHighlightedDay != touchedItem) {
+ mHighlightedDay = touchedItem;
+ mPreviouslyHighlightedDay = touchedItem;
invalidate();
}
if (action == MotionEvent.ACTION_DOWN && touchedItem < 0) {
@@ -342,7 +357,8 @@
// Fall through.
case MotionEvent.ACTION_CANCEL:
// Reset touched day on stream end.
- mTouchedItem = -1;
+ mHighlightedDay = -1;
+ mIsTouchHighlighted = false;
invalidate();
break;
}
@@ -350,6 +366,228 @@
}
@Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ // We need to handle focus change within the SimpleMonthView because we are simulating
+ // multiple Views. The arrow keys will move between days until there is no space (no
+ // day to the left, top, right, or bottom). Focus forward and back jumps out of the
+ // SimpleMonthView, skipping over other SimpleMonthViews in the parent ViewPager
+ // to the next focusable View in the hierarchy.
+ boolean focusChanged = false;
+ switch (event.getKeyCode()) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (event.hasNoModifiers()) {
+ focusChanged = moveOneDay(isLayoutRtl());
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (event.hasNoModifiers()) {
+ focusChanged = moveOneDay(!isLayoutRtl());
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (event.hasNoModifiers()) {
+ ensureFocusedDay();
+ if (mHighlightedDay > 7) {
+ mHighlightedDay -= 7;
+ focusChanged = true;
+ }
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (event.hasNoModifiers()) {
+ ensureFocusedDay();
+ if (mHighlightedDay <= mDaysInMonth - 7) {
+ mHighlightedDay += 7;
+ focusChanged = true;
+ }
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_ENTER:
+ if (mHighlightedDay != -1) {
+ onDayClicked(mHighlightedDay);
+ return true;
+ }
+ break;
+ case KeyEvent.KEYCODE_TAB: {
+ int focusChangeDirection = 0;
+ if (event.hasNoModifiers()) {
+ focusChangeDirection = View.FOCUS_FORWARD;
+ } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+ focusChangeDirection = View.FOCUS_BACKWARD;
+ }
+ if (focusChangeDirection != 0) {
+ final ViewParent parent = getParent();
+ // move out of the ViewPager next/previous
+ View nextFocus = this;
+ do {
+ nextFocus = nextFocus.focusSearch(focusChangeDirection);
+ } while (nextFocus != null && nextFocus != this &&
+ nextFocus.getParent() == parent);
+ if (nextFocus != null) {
+ nextFocus.requestFocus();
+ return true;
+ }
+ }
+ break;
+ }
+ }
+ if (focusChanged) {
+ invalidate();
+ return true;
+ } else {
+ return super.onKeyDown(keyCode, event);
+ }
+ }
+
+ private boolean moveOneDay(boolean positive) {
+ ensureFocusedDay();
+ boolean focusChanged = false;
+ if (positive) {
+ if (!isLastDayOfWeek(mHighlightedDay) && mHighlightedDay < mDaysInMonth) {
+ mHighlightedDay++;
+ focusChanged = true;
+ }
+ } else {
+ if (!isFirstDayOfWeek(mHighlightedDay) && mHighlightedDay > 1) {
+ mHighlightedDay--;
+ focusChanged = true;
+ }
+ }
+ return focusChanged;
+ }
+
+ @Override
+ protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
+ @Nullable Rect previouslyFocusedRect) {
+ if (gainFocus) {
+ // If we've gained focus through arrow keys, we should find the day closest
+ // to the focus rect. If we've gained focus through forward/back, we should
+ // focus on the selected day if there is one.
+ final int offset = findDayOffset();
+ switch(direction) {
+ case View.FOCUS_RIGHT: {
+ int row = findClosestRow(previouslyFocusedRect);
+ mHighlightedDay = row == 0 ? 1 : (row * DAYS_IN_WEEK) - offset + 1;
+ break;
+ }
+ case View.FOCUS_LEFT: {
+ int row = findClosestRow(previouslyFocusedRect) + 1;
+ mHighlightedDay = Math.min(mDaysInMonth, (row * DAYS_IN_WEEK) - offset);
+ break;
+ }
+ case View.FOCUS_DOWN: {
+ final int col = findClosestColumn(previouslyFocusedRect);
+ final int day = col - offset + 1;
+ mHighlightedDay = day < 1 ? day + DAYS_IN_WEEK : day;
+ break;
+ }
+ case View.FOCUS_UP: {
+ final int col = findClosestColumn(previouslyFocusedRect);
+ final int maxWeeks = (offset + mDaysInMonth) / DAYS_IN_WEEK;
+ final int day = col - offset + (DAYS_IN_WEEK * maxWeeks) + 1;
+ mHighlightedDay = day > mDaysInMonth ? day - DAYS_IN_WEEK : day;
+ break;
+ }
+ }
+ ensureFocusedDay();
+ invalidate();
+ }
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ }
+
+ /**
+ * Returns the row (0 indexed) closest to previouslyFocusedRect or center if null.
+ */
+ private int findClosestRow(@Nullable Rect previouslyFocusedRect) {
+ if (previouslyFocusedRect == null) {
+ return 3;
+ } else {
+ int centerY = previouslyFocusedRect.centerY();
+
+ final TextPaint p = mDayPaint;
+ final int headerHeight = mMonthHeight + mDayOfWeekHeight;
+ final int rowHeight = mDayHeight;
+
+ // Text is vertically centered within the row height.
+ final float halfLineHeight = (p.ascent() + p.descent()) / 2f;
+ final int rowCenter = headerHeight + rowHeight / 2;
+
+ centerY -= rowCenter - halfLineHeight;
+ int row = Math.round(centerY / (float) rowHeight);
+ final int maxDay = findDayOffset() + mDaysInMonth;
+ final int maxRows = (maxDay / DAYS_IN_WEEK) - ((maxDay % DAYS_IN_WEEK == 0) ? 1 : 0);
+
+ row = MathUtils.constrain(row, 0, maxRows);
+ return row;
+ }
+ }
+
+ /**
+ * Returns the column (0 indexed) closest to the previouslyFocusedRect or center if null.
+ * The 0 index is related to the first day of the week.
+ */
+ private int findClosestColumn(@Nullable Rect previouslyFocusedRect) {
+ if (previouslyFocusedRect == null) {
+ return DAYS_IN_WEEK / 2;
+ } else {
+ int centerX = previouslyFocusedRect.centerX() - mPaddingLeft;
+ final int columnFromLeft =
+ MathUtils.constrain(centerX / mCellWidth, 0, DAYS_IN_WEEK - 1);
+ return isLayoutRtl() ? DAYS_IN_WEEK - columnFromLeft - 1: columnFromLeft;
+ }
+ }
+
+ @Override
+ public void getFocusedRect(Rect r) {
+ if (mHighlightedDay > 0) {
+ getBoundsForDay(mHighlightedDay, r);
+ } else {
+ super.getFocusedRect(r);
+ }
+ }
+
+ @Override
+ protected void onFocusLost() {
+ if (!mIsTouchHighlighted) {
+ // Unhighlight a day.
+ mPreviouslyHighlightedDay = mHighlightedDay;
+ mHighlightedDay = -1;
+ invalidate();
+ }
+ super.onFocusLost();
+ }
+
+ /**
+ * Ensure some day is highlighted. If a day isn't highlighted, it chooses the selected day,
+ * if possible, or the first day of the month if not.
+ */
+ private void ensureFocusedDay() {
+ if (mHighlightedDay != -1) {
+ return;
+ }
+ if (mPreviouslyHighlightedDay != -1) {
+ mHighlightedDay = mPreviouslyHighlightedDay;
+ return;
+ }
+ if (mActivatedDay != -1) {
+ mHighlightedDay = mActivatedDay;
+ return;
+ }
+ mHighlightedDay = 1;
+ }
+
+ private boolean isFirstDayOfWeek(int day) {
+ final int offset = findDayOffset();
+ return (offset + day - 1) % DAYS_IN_WEEK == 0;
+ }
+
+ private boolean isLastDayOfWeek(int day) {
+ final int offset = findDayOffset();
+ return (offset + day) % DAYS_IN_WEEK == 0;
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
final int paddingLeft = getPaddingLeft();
final int paddingTop = getPaddingTop();
@@ -432,12 +670,15 @@
}
final boolean isDayActivated = mActivatedDay == day;
+ final boolean isDayHighlighted = mHighlightedDay == day;
if (isDayActivated) {
stateMask |= StateSet.VIEW_STATE_ACTIVATED;
// Adjust the circle to be centered on the row.
- canvas.drawCircle(colCenterRtl, rowCenter, mDaySelectorRadius, mDaySelectorPaint);
- } else if (mTouchedItem == day) {
+ final Paint paint = isDayHighlighted ? mDayHighlightSelectorPaint :
+ mDaySelectorPaint;
+ canvas.drawCircle(colCenterRtl, rowCenter, mDaySelectorRadius, paint);
+ } else if (isDayHighlighted) {
stateMask |= StateSet.VIEW_STATE_PRESSED;
if (isDayEnabled) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f7eaedd..c54a574 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -310,6 +310,14 @@
*/
static final int PROCESS_TEXT_REQUEST_CODE = 100;
+ /**
+ * Return code of {@link #doKeyDown}.
+ */
+ private static final int KEY_EVENT_NOT_HANDLED = 0;
+ private static final int KEY_EVENT_HANDLED = -1;
+ private static final int KEY_DOWN_HANDLED_BY_KEY_LISTENER = 1;
+ private static final int KEY_DOWN_HANDLED_BY_MOVEMENT_METHOD = 2;
+
// System wide time for last cut, copy or text changed action.
static long sLastCutCopyOrTextChangedTime;
@@ -5955,8 +5963,8 @@
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- int which = doKeyDown(keyCode, event, null);
- if (which == 0) {
+ final int which = doKeyDown(keyCode, event, null);
+ if (which == KEY_EVENT_NOT_HANDLED) {
return super.onKeyDown(keyCode, event);
}
@@ -5966,13 +5974,12 @@
@Override
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN);
-
- int which = doKeyDown(keyCode, down, event);
- if (which == 0) {
+ final int which = doKeyDown(keyCode, down, event);
+ if (which == KEY_EVENT_NOT_HANDLED) {
// Go through default dispatching.
return super.onKeyMultiple(keyCode, repeatCount, event);
}
- if (which == -1) {
+ if (which == KEY_EVENT_HANDLED) {
// Consumed the whole thing.
return true;
}
@@ -5985,7 +5992,7 @@
// It would be nice if those interfaces had an onKeyMultiple() method,
// but adding that is a more complicated change.
KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP);
- if (which == 1) {
+ if (which == KEY_DOWN_HANDLED_BY_KEY_LISTENER) {
// mEditor and mEditor.mInput are not null from doKeyDown
mEditor.mKeyListener.onKeyUp(this, (Editable)mText, keyCode, up);
while (--repeatCount > 0) {
@@ -5994,7 +6001,7 @@
}
hideErrorIfUnchanged();
- } else if (which == 2) {
+ } else if (which == KEY_DOWN_HANDLED_BY_MOVEMENT_METHOD) {
// mMovement is not null from doKeyDown
mMovement.onKeyUp(this, (Spannable)mText, keyCode, up);
while (--repeatCount > 0) {
@@ -6051,7 +6058,7 @@
private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) {
if (!isEnabled()) {
- return 0;
+ return KEY_EVENT_NOT_HANDLED;
}
// If this is the initial keydown, we don't want to prevent a movement away from this view.
@@ -6078,7 +6085,7 @@
this, EditorInfo.IME_NULL, event)) {
mEditor.mInputContentType.enterDown = true;
// We are consuming the enter key for them.
- return -1;
+ return KEY_EVENT_HANDLED;
}
}
@@ -6088,9 +6095,9 @@
if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
|| shouldAdvanceFocusOnEnter()) {
if (hasOnClickListeners()) {
- return 0;
+ return KEY_EVENT_NOT_HANDLED;
}
- return -1;
+ return KEY_EVENT_HANDLED;
}
}
break;
@@ -6098,7 +6105,7 @@
case KeyEvent.KEYCODE_DPAD_CENTER:
if (event.hasNoModifiers()) {
if (shouldAdvanceFocusOnEnter()) {
- return 0;
+ return KEY_EVENT_NOT_HANDLED;
}
}
break;
@@ -6106,7 +6113,7 @@
case KeyEvent.KEYCODE_TAB:
if (event.hasNoModifiers() || event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
if (shouldAdvanceFocusOnTab()) {
- return 0;
+ return KEY_EVENT_NOT_HANDLED;
}
}
break;
@@ -6115,14 +6122,14 @@
case KeyEvent.KEYCODE_BACK:
if (mEditor != null && mEditor.mTextActionMode != null) {
stopTextActionMode();
- return -1;
+ return KEY_EVENT_HANDLED;
}
break;
case KeyEvent.KEYCODE_CUT:
if (event.hasNoModifiers() && canCut()) {
if (onTextContextMenuItem(ID_CUT)) {
- return -1;
+ return KEY_EVENT_HANDLED;
}
}
break;
@@ -6130,7 +6137,7 @@
case KeyEvent.KEYCODE_COPY:
if (event.hasNoModifiers() && canCopy()) {
if (onTextContextMenuItem(ID_COPY)) {
- return -1;
+ return KEY_EVENT_HANDLED;
}
}
break;
@@ -6138,7 +6145,7 @@
case KeyEvent.KEYCODE_PASTE:
if (event.hasNoModifiers() && canPaste()) {
if (onTextContextMenuItem(ID_PASTE)) {
- return -1;
+ return KEY_EVENT_HANDLED;
}
}
break;
@@ -6154,7 +6161,7 @@
hideErrorIfUnchanged();
doDown = false;
if (handled) {
- return -1;
+ return KEY_EVENT_HANDLED;
}
} catch (AbstractMethodError e) {
// onKeyOther was added after 1.0, so if it isn't
@@ -6170,7 +6177,7 @@
keyCode, event);
endBatchEdit();
hideErrorIfUnchanged();
- if (handled) return 1;
+ if (handled) return KEY_DOWN_HANDLED_BY_KEY_LISTENER;
}
}
@@ -6185,7 +6192,7 @@
otherEvent);
doDown = false;
if (handled) {
- return -1;
+ return KEY_EVENT_HANDLED;
}
} catch (AbstractMethodError e) {
// onKeyOther was added after 1.0, so if it isn't
@@ -6197,12 +6204,13 @@
if (event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(keyCode)) {
mPreventDefaultMovement = true;
}
- return 2;
+ return KEY_DOWN_HANDLED_BY_MOVEMENT_METHOD;
}
}
}
- return mPreventDefaultMovement && !KeyEvent.isModifierKey(keyCode) ? -1 : 0;
+ return mPreventDefaultMovement && !KeyEvent.isModifierKey(keyCode) ?
+ KEY_EVENT_HANDLED : KEY_EVENT_NOT_HANDLED;
}
/**
diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java
index 89e59f9..96624d2 100644
--- a/core/java/android/widget/YearPickerView.java
+++ b/core/java/android/widget/YearPickerView.java
@@ -38,8 +38,6 @@
private OnYearSelectedListener mOnYearSelectedListener;
- private long mCurrentTimeMillis;
-
public YearPickerView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.listViewStyle);
}
@@ -79,10 +77,6 @@
mOnYearSelectedListener = listener;
}
- public void setDate(long currentTimeMillis) {
- mCurrentTimeMillis = currentTimeMillis;
- }
-
/**
* Sets the currently selected year. Jumps immediately to the new year.
*
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 6217d6e..948a6bb 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -1095,7 +1095,16 @@
View child = getChildAt(i);
ii = infoForChild(child);
if (ii != null && ii.position == mCurItem) {
- if (child.requestFocus(focusDirection)) {
+ final Rect focusRect;
+ if (currentFocused == null) {
+ focusRect = null;
+ } else {
+ focusRect = mTempRect;
+ currentFocused.getFocusedRect(mTempRect);
+ offsetDescendantRectToMyCoords(currentFocused, mTempRect);
+ offsetRectIntoDescendantCoords(child, mTempRect);
+ }
+ if (child.requestFocus(focusDirection, focusRect)) {
break;
}
}
@@ -1321,6 +1330,11 @@
}
}
+ public Object getCurrent() {
+ final ItemInfo itemInfo = infoForPosition(getCurrentItem());
+ return itemInfo == null ? null : itemInfo.object;
+ }
+
@Override
public void removeView(View view) {
if (mInLayout) {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index ffc69a9..4e93730 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -888,21 +888,22 @@
profileMaxStackDepth,
"-Xprofile-max-stack-depth:");
- /*
- * Tracing options.
- */
- property_get("dalvik.vm.method-trace", propBuf, "false");
- if (strcmp(propBuf, "true") == 0) {
- addOption("-Xmethod-trace");
- parseRuntimeOption("dalvik.vm.method-trace-file",
- methodTraceFileBuf,
- "-Xmethod-trace-file:");
- parseRuntimeOption("dalvik.vm.method-trace-file-siz",
- methodTraceFileSizeBuf,
- "-Xmethod-trace-file-size:");
- property_get("dalvik.vm.method-trace-stream", propBuf, "false");
+ // Trace files are stored in /data/misc/trace which is writable only in debug mode.
+ property_get("ro.debuggable", propBuf, "0");
+ if (strcmp(propBuf, "1") == 0) {
+ property_get("dalvik.vm.method-trace", propBuf, "false");
if (strcmp(propBuf, "true") == 0) {
- addOption("-Xmethod-trace-stream");
+ addOption("-Xmethod-trace");
+ parseRuntimeOption("dalvik.vm.method-trace-file",
+ methodTraceFileBuf,
+ "-Xmethod-trace-file:");
+ parseRuntimeOption("dalvik.vm.method-trace-file-siz",
+ methodTraceFileSizeBuf,
+ "-Xmethod-trace-file-size:");
+ property_get("dalvik.vm.method-trace-stream", propBuf, "false");
+ if (strcmp(propBuf, "true") == 0) {
+ addOption("-Xmethod-trace-stream");
+ }
}
}
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 568473c..c8b1784 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -184,51 +184,43 @@
jint _minorRemaining;
EGLint *minor = (EGLint *) 0;
- if (!major_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "major == null";
- goto exit;
+ if (major_ref) {
+ if (majorOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "majorOffset < 0";
+ goto exit;
+ }
+ _majorRemaining = _env->GetArrayLength(major_ref) - majorOffset;
+ if (_majorRemaining < 1) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "length - majorOffset < 1 < needed";
+ goto exit;
+ }
+ major_base = (EGLint *)
+ _env->GetIntArrayElements(major_ref, (jboolean *)0);
+ major = major_base + majorOffset;
}
- if (majorOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "majorOffset < 0";
- goto exit;
- }
- _majorRemaining = _env->GetArrayLength(major_ref) - majorOffset;
- if (_majorRemaining < 1) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length - majorOffset < 1 < needed";
- goto exit;
- }
- major_base = (EGLint *)
- _env->GetIntArrayElements(major_ref, (jboolean *)0);
- major = major_base + majorOffset;
- if (!minor_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "minor == null";
- goto exit;
+ if (minor_ref) {
+ if (minorOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "minorOffset < 0";
+ goto exit;
+ }
+ _minorRemaining = _env->GetArrayLength(minor_ref) - minorOffset;
+ if (_minorRemaining < 1) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "length - minorOffset < 1 < needed";
+ goto exit;
+ }
+ minor_base = (EGLint *)
+ _env->GetIntArrayElements(minor_ref, (jboolean *)0);
+ minor = minor_base + minorOffset;
}
- if (minorOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "minorOffset < 0";
- goto exit;
- }
- _minorRemaining = _env->GetArrayLength(minor_ref) - minorOffset;
- if (_minorRemaining < 1) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length - minorOffset < 1 < needed";
- goto exit;
- }
- minor_base = (EGLint *)
- _env->GetIntArrayElements(minor_ref, (jboolean *)0);
- minor = minor_base + minorOffset;
_returnValue = eglInitialize(
(EGLDisplay)dpy_native,
@@ -289,26 +281,22 @@
jint _num_configRemaining;
EGLint *num_config = (EGLint *) 0;
- if (!configs_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "configs == null";
- goto exit;
+ if (configs_ref) {
+ if (configsOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "configsOffset < 0";
+ goto exit;
+ }
+ _configsRemaining = _env->GetArrayLength(configs_ref) - configsOffset;
+ if (_configsRemaining < config_size) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "length - configsOffset < config_size < needed";
+ goto exit;
+ }
+ configs = new EGLConfig[_configsRemaining];
}
- if (configsOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "configsOffset < 0";
- goto exit;
- }
- _configsRemaining = _env->GetArrayLength(configs_ref) - configsOffset;
- if (_configsRemaining < config_size) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length - configsOffset < config_size < needed";
- goto exit;
- }
- configs = new EGLConfig[_configsRemaining];
if (!num_config_ref) {
_exception = 1;
@@ -401,26 +389,22 @@
goto exit;
}
- if (!configs_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "configs == null";
- goto exit;
+ if (configs_ref) {
+ if (configsOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "configsOffset < 0";
+ goto exit;
+ }
+ _configsRemaining = _env->GetArrayLength(configs_ref) - configsOffset;
+ if (_configsRemaining < config_size) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "length - configsOffset < config_size < needed";
+ goto exit;
+ }
+ configs = new EGLConfig[_configsRemaining];
}
- if (configsOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "configsOffset < 0";
- goto exit;
- }
- _configsRemaining = _env->GetArrayLength(configs_ref) - configsOffset;
- if (_configsRemaining < config_size) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length - configsOffset < config_size < needed";
- goto exit;
- }
- configs = new EGLConfig[_configsRemaining];
if (!num_config_ref) {
_exception = 1;
@@ -546,18 +530,32 @@
EGLint *attrib_list = (EGLint *) 0;
android::sp<ANativeWindow> window;
- if (!attrib_list_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "attrib_list == null";
- goto exit;
+ if (attrib_list_ref) {
+ if (offset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "offset < 0";
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+ attrib_list_base = (EGLint *)
+ _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
+ attrib_list = attrib_list_base + offset;
+ attrib_list_sentinel = 0;
+ for (int i = _remaining - 1; i >= 0; i--) {
+ if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
+ attrib_list_sentinel = 1;
+ break;
+ }
+ }
+ if (attrib_list_sentinel == 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "attrib_list must contain EGL_NONE!";
+ goto exit;
+ }
}
- if (offset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "offset < 0";
- goto exit;
- }
+
if (win == NULL) {
not_valid_surface:
_exception = 1;
@@ -571,24 +569,6 @@
if (window == NULL)
goto not_valid_surface;
- _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
- attrib_list_base = (EGLint *)
- _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
- attrib_list = attrib_list_base + offset;
- attrib_list_sentinel = 0;
- for (int i = _remaining - 1; i >= 0; i--) {
- if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
- attrib_list_sentinel = 1;
- break;
- }
- }
- if (attrib_list_sentinel == 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "attrib_list must contain EGL_NONE!";
- goto exit;
- }
-
_returnValue = eglCreateWindowSurface(
(EGLDisplay)dpy_native,
(EGLConfig)config_native,
@@ -703,34 +683,30 @@
jint _remaining;
EGLint *attrib_list = (EGLint *) 0;
- if (!attrib_list_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "attrib_list == null";
- goto exit;
- }
- if (offset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "offset < 0";
- goto exit;
- }
- _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
- attrib_list_base = (EGLint *)
- _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
- attrib_list = attrib_list_base + offset;
- attrib_list_sentinel = false;
- for (int i = _remaining - 1; i >= 0; i--) {
- if (attrib_list[i] == EGL_NONE){
- attrib_list_sentinel = true;
- break;
+ if (attrib_list_ref) {
+ if (offset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "offset < 0";
+ goto exit;
}
- }
- if (attrib_list_sentinel == false) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "attrib_list must contain EGL_NONE!";
- goto exit;
+ _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+ attrib_list_base = (EGLint *)
+ _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
+ attrib_list = attrib_list_base + offset;
+ attrib_list_sentinel = false;
+ for (int i = _remaining - 1; i >= 0; i--) {
+ if (attrib_list[i] == EGL_NONE){
+ attrib_list_sentinel = true;
+ break;
+ }
+ }
+ if (attrib_list_sentinel == false) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "attrib_list must contain EGL_NONE!";
+ goto exit;
+ }
}
_returnValue = eglCreatePbufferSurface(
@@ -882,34 +858,30 @@
jint _remaining;
EGLint *attrib_list = (EGLint *) 0;
- if (!attrib_list_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "attrib_list == null";
- goto exit;
- }
- if (offset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "offset < 0";
- goto exit;
- }
- _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
- attrib_list_base = (EGLint *)
- _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
- attrib_list = attrib_list_base + offset;
- attrib_list_sentinel = false;
- for (int i = _remaining - 1; i >= 0; i--) {
- if (attrib_list[i] == EGL_NONE){
- attrib_list_sentinel = true;
- break;
+ if (attrib_list_ref) {
+ if (offset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "offset < 0";
+ goto exit;
}
- }
- if (attrib_list_sentinel == false) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "attrib_list must contain EGL_NONE!";
- goto exit;
+ _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+ attrib_list_base = (EGLint *)
+ _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
+ attrib_list = attrib_list_base + offset;
+ attrib_list_sentinel = false;
+ for (int i = _remaining - 1; i >= 0; i--) {
+ if (attrib_list[i] == EGL_NONE){
+ attrib_list_sentinel = true;
+ break;
+ }
+ }
+ if (attrib_list_sentinel == false) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "attrib_list must contain EGL_NONE!";
+ goto exit;
+ }
}
_returnValue = eglCreatePbufferFromClientBuffer(
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index b9f61a9..ac3bf7a 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -1783,22 +1783,18 @@
jint _nameRemaining;
char *name = (char *) 0;
- if (!length_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length == null";
- goto exit;
+ if (length_ref) {
+ if (lengthOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "lengthOffset < 0";
+ goto exit;
+ }
+ _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+ length_base = (GLsizei *)
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
+ length = length_base + lengthOffset;
}
- if (lengthOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "lengthOffset < 0";
- goto exit;
- }
- _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- length_base = (GLsizei *)
- _env->GetIntArrayElements(length_ref, (jboolean *)0);
- length = length_base + lengthOffset;
if (!size_ref) {
_exception = 1;
@@ -2111,22 +2107,18 @@
jint _nameRemaining;
char *name = (char *) 0;
- if (!length_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length == null";
- goto exit;
+ if (length_ref) {
+ if (lengthOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "lengthOffset < 0";
+ goto exit;
+ }
+ _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+ length_base = (GLsizei *)
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
+ length = length_base + lengthOffset;
}
- if (lengthOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "lengthOffset < 0";
- goto exit;
- }
- _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- length_base = (GLsizei *)
- _env->GetIntArrayElements(length_ref, (jboolean *)0);
- length = length_base + lengthOffset;
if (!size_ref) {
_exception = 1;
@@ -2434,28 +2426,24 @@
jint _shadersRemaining;
GLuint *shaders = (GLuint *) 0;
- if (!count_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "count == null";
- goto exit;
+ if (count_ref) {
+ if (countOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "countOffset < 0";
+ goto exit;
+ }
+ _countRemaining = _env->GetArrayLength(count_ref) - countOffset;
+ if (_countRemaining < 1) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "length - countOffset < 1 < needed";
+ goto exit;
+ }
+ count_base = (GLsizei *)
+ _env->GetIntArrayElements(count_ref, (jboolean *)0);
+ count = count_base + countOffset;
}
- if (countOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "countOffset < 0";
- goto exit;
- }
- _countRemaining = _env->GetArrayLength(count_ref) - countOffset;
- if (_countRemaining < 1) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length - countOffset < 1 < needed";
- goto exit;
- }
- count_base = (GLsizei *)
- _env->GetIntArrayElements(count_ref, (jboolean *)0);
- count = count_base + countOffset;
if (!shaders_ref) {
_exception = 1;
@@ -2526,20 +2514,18 @@
goto exit;
}
}
- if (shaders_buf) {
- shaders = (GLuint *)getPointer(_env, shaders_buf, (jarray*)&_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
- if (_shadersRemaining < maxcount) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "remaining() < maxcount < needed";
- goto exit;
- }
+ shaders = (GLuint *)getPointer(_env, shaders_buf, (jarray*)&_shadersArray, &_shadersRemaining, &_shadersBufferOffset);
+ if (_shadersRemaining < maxcount) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "remaining() < maxcount < needed";
+ goto exit;
}
if (count_buf && count == NULL) {
char * _countBase = (char *)_env->GetIntArrayElements(_countArray, (jboolean *) 0);
count = (GLsizei *) (_countBase + _countBufferOffset);
}
- if (shaders_buf && shaders == NULL) {
+ if (shaders == NULL) {
char * _shadersBase = (char *)_env->GetIntArrayElements(_shadersArray, (jboolean *) 0);
shaders = (GLuint *) (_shadersBase + _shadersBufferOffset);
}
@@ -3262,22 +3248,18 @@
jint _sourceRemaining;
char *source = (char *) 0;
- if (!length_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length == null";
- goto exit;
+ if (length_ref) {
+ if (lengthOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "lengthOffset < 0";
+ goto exit;
+ }
+ _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+ length_base = (GLsizei *)
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
+ length = length_base + lengthOffset;
}
- if (lengthOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "lengthOffset < 0";
- goto exit;
- }
- _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- length_base = (GLsizei *)
- _env->GetIntArrayElements(length_ref, (jboolean *)0);
- length = length_base + lengthOffset;
if (!source_ref) {
_exception = 1;
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 8eb5044..c9b5af7 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -501,8 +501,10 @@
jint _remaining;
GLvoid *pixels = (GLvoid *) 0;
- pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
- if (pixels == NULL) {
+ if (pixels_buf) {
+ pixels = (GLvoid *)getPointer(_env, pixels_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
+ }
+ if (pixels_buf && pixels == NULL) {
char * _pixelsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
pixels = (GLvoid *) (_pixelsBase + _bufferOffset);
}
@@ -1910,22 +1912,18 @@
jint _nameRemaining;
char *name = (char *) 0;
- if (!length_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length == null";
- goto exit;
+ if (length_ref) {
+ if (lengthOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "lengthOffset < 0";
+ goto exit;
+ }
+ _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+ length_base = (GLsizei *)
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
+ length = length_base + lengthOffset;
}
- if (lengthOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "lengthOffset < 0";
- goto exit;
- }
- _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- length_base = (GLsizei *)
- _env->GetIntArrayElements(length_ref, (jboolean *)0);
- length = length_base + lengthOffset;
if (!size_ref) {
_exception = 1;
@@ -3591,22 +3589,18 @@
jint _nameRemaining;
GLchar* _name = (GLchar*)0;
- if (!length_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length == null";
- goto exit;
+ if (length_ref) {
+ if (lengthOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "lengthOffset < 0";
+ goto exit;
+ }
+ _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+ _length_base = (GLsizei*)_env->GetIntArrayElements(
+ length_ref, (jboolean*)0);
+ _length = _length_base + lengthOffset;
}
- if (lengthOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "lengthOffset < 0";
- goto exit;
- }
- _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- _length_base = (GLsizei*)_env->GetIntArrayElements(
- length_ref, (jboolean*)0);
- _length = _length_base + lengthOffset;
if (!name_ref) {
_exception = 1;
@@ -3900,22 +3894,18 @@
jint _valuesRemaining;
GLint *values = (GLint *) 0;
- if (!length_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length == null";
- goto exit;
+ if (length_ref) {
+ if (lengthOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "lengthOffset < 0";
+ goto exit;
+ }
+ _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+ length_base = (GLsizei *)
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
+ length = length_base + lengthOffset;
}
- if (lengthOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "lengthOffset < 0";
- goto exit;
- }
- _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- length_base = (GLsizei *)
- _env->GetIntArrayElements(length_ref, (jboolean *)0);
- length = length_base + lengthOffset;
if (!values_ref) {
_exception = 1;
@@ -3969,9 +3959,11 @@
jint _valuesRemaining;
GLint *values = (GLint *) 0;
- length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ if (length_buf) {
+ length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ }
values = (GLint *)getPointer(_env, values_buf, (jarray*)&_valuesArray, &_valuesRemaining, &_valuesBufferOffset);
- if (length == NULL) {
+ if (length_buf && length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
}
@@ -4772,22 +4764,18 @@
jint _binaryRemaining;
GLvoid *binary = (GLvoid *) 0;
- if (!length_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length == null";
- goto exit;
+ if (length_ref) {
+ if (lengthOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "lengthOffset < 0";
+ goto exit;
+ }
+ _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+ length_base = (GLsizei *)
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
+ length = length_base + lengthOffset;
}
- if (lengthOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "lengthOffset < 0";
- goto exit;
- }
- _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- length_base = (GLsizei *)
- _env->GetIntArrayElements(length_ref, (jboolean *)0);
- length = length_base + lengthOffset;
if (!binaryFormat_ref) {
_exception = 1;
@@ -4853,10 +4841,12 @@
jint _binaryRemaining;
GLvoid *binary = (GLvoid *) 0;
- length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ if (length_buf) {
+ length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ }
binaryFormat = (GLenum *)getPointer(_env, binaryFormat_buf, (jarray*)&_binaryFormatArray, &_binaryFormatRemaining, &_binaryFormatBufferOffset);
binary = (GLvoid *)getPointer(_env, binary_buf, (jarray*)&_binaryArray, &_binaryRemaining, &_binaryBufferOffset);
- if (length == NULL) {
+ if (length_buf && length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
}
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index e427388..5751add 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -714,22 +714,18 @@
_env->GetIntArrayElements(props_ref, (jboolean *)0);
props = props_base + propsOffset;
- if (!length_ref) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "length == null";
- goto exit;
+ if (length_ref) {
+ if (lengthOffset < 0) {
+ _exception = 1;
+ _exceptionType = "java/lang/IllegalArgumentException";
+ _exceptionMessage = "lengthOffset < 0";
+ goto exit;
+ }
+ _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+ length_base = (GLsizei *)
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
+ length = length_base + lengthOffset;
}
- if (lengthOffset < 0) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "lengthOffset < 0";
- goto exit;
- }
- _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- length_base = (GLsizei *)
- _env->GetIntArrayElements(length_ref, (jboolean *)0);
- length = length_base + lengthOffset;
if (!params_ref) {
_exception = 1;
@@ -795,13 +791,15 @@
GLint *params = (GLint *) 0;
props = (GLenum *)getPointer(_env, props_buf, (jarray*)&_propsArray, &_propsRemaining, &_propsBufferOffset);
- length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ if (length_buf) {
+ length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ }
params = (GLint *)getPointer(_env, params_buf, (jarray*)&_paramsArray, &_paramsRemaining, &_paramsBufferOffset);
if (props == NULL) {
char * _propsBase = (char *)_env->GetIntArrayElements(_propsArray, (jboolean *) 0);
props = (GLenum *) (_propsBase + _propsBufferOffset);
}
- if (length == NULL) {
+ if (length_buf && length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
}
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
index 180c693..5be7be0 100644
--- a/core/jni/android_opengl_GLES31Ext.cpp
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -646,13 +646,9 @@
const char * _exceptionMessage = NULL;
const char* _nativelabel = 0;
- if (!label) {
- _exception = 1;
- _exceptionType = "java/lang/IllegalArgumentException";
- _exceptionMessage = "label == null";
- goto exit;
+ if (label) {
+ _nativelabel = _env->GetStringUTFChars(label, 0);
}
- _nativelabel = _env->GetStringUTFChars(label, 0);
glObjectLabelKHR(
(GLenum)identifier,
@@ -660,8 +656,6 @@
(GLsizei)length,
(GLchar *)_nativelabel
);
-
-exit:
if (_nativelabel) {
_env->ReleaseStringUTFChars(label, _nativelabel);
}
diff --git a/core/res/res/layout/date_picker_header_material.xml b/core/res/res/layout/date_picker_header_material.xml
index a4388f6..821b588 100644
--- a/core/res/res/layout/date_picker_header_material.xml
+++ b/core/res/res/layout/date_picker_header_material.xml
@@ -19,19 +19,27 @@
android:id="@+id/date_picker_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingBottom="18dp"
android:paddingStart="?attr/dialogPreferredPadding"
android:paddingEnd="?attr/dialogPreferredPadding"
- android:orientation="vertical">
+ android:paddingTop="16dp"
+ android:paddingBottom="18dp"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
- <!-- Top padding should stay on this view so that
- the touch target is a bit larger. -->
<TextView
android:id="@+id/date_picker_header_year"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingTop="16dp"
- android:textAppearance="@style/TextAppearance.Material.DatePicker.YearLabel" />
+ android:focusable="true"
+ android:layout_marginStart="-8dp"
+ android:layout_marginEnd="-8dp"
+ android:layout_marginTop="-8dp"
+ android:layout_marginBottom="-8dp"
+ android:padding="8dp"
+ android:background="?attr/selectableItemBackground"
+ android:textAppearance="@style/TextAppearance.Material.DatePicker.YearLabel"
+ android:nextFocusForward="@+id/prev" />
<TextView
android:id="@+id/date_picker_header_date"
diff --git a/core/res/res/layout/date_picker_month_item_material.xml b/core/res/res/layout/date_picker_month_item_material.xml
index cb79cee..52f7b8e 100644
--- a/core/res/res/layout/date_picker_month_item_material.xml
+++ b/core/res/res/layout/date_picker_month_item_material.xml
@@ -21,4 +21,5 @@
android:layout_height="wrap_content"
android:paddingStart="@dimen/day_picker_padding_horizontal"
android:paddingEnd="@dimen/day_picker_padding_horizontal"
- android:paddingTop="@dimen/day_picker_padding_top" />
+ android:paddingTop="@dimen/day_picker_padding_top"
+ android:focusable="true"/>
diff --git a/core/res/res/layout/day_picker_content_material.xml b/core/res/res/layout/day_picker_content_material.xml
index b582d74..d77e8dc 100644
--- a/core/res/res/layout/day_picker_content_material.xml
+++ b/core/res/res/layout/day_picker_content_material.xml
@@ -33,7 +33,9 @@
android:src="@drawable/ic_chevron_start"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/date_picker_prev_month_button"
- android:visibility="invisible" />
+ android:visibility="invisible"
+ android:nextFocusForward="@+id/next"
+ android:nextFocusDown="@+id/month_view" />
<ImageButton
android:id="@+id/next"
@@ -44,6 +46,8 @@
android:src="@drawable/ic_chevron_end"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/date_picker_next_month_button"
- android:visibility="invisible" />
+ android:visibility="invisible"
+ android:nextFocusForward="@+id/month_view"
+ android:nextFocusDown="@+id/month_view"/>
</FrameLayout>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index b58c0bd..7a7a814 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -420,7 +420,7 @@
<string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autoriser l\'application à utiliser le matériel d\'empreintes digitales pour l\'authentification"</string>
<string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte numérique partiellement détectée. Veuillez réessayer."</string>
<string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de reconnaître l\'empreinte numérique. Veuillez réessayer."</string>
- <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le capteur d\'empreintes numériques est sale. Veuillez le nettoyer, puis réessayer."</string>
+ <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le lecteur d\'empreintes numériques est sale. Veuillez le nettoyer, puis réessayer."</string>
<string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Vous avez déplacé votre doigt trop rapidement. Veuillez réessayer."</string>
<string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string>
<string-array name="fingerprint_acquired_vendor">
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index f4b6346..a6fdad3 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -699,7 +699,7 @@
<string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Fiók feloldása"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Túl sok mintarajzolási próbálkozás"</string>
<string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"A feloldáshoz jelentkezzen be Google-fiókjával."</string>
- <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Felhasználónév (e-mail cím)"</string>
+ <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Felhasználónév (e-mail-cím)"</string>
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Jelszó"</string>
<string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Bejelentkezés"</string>
<string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Érvénytelen felhasználónév vagy jelszó."</string>
@@ -1277,7 +1277,7 @@
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"A PIN kódok nem egyeznek."</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Túl sok mintarajzolási próbálkozás"</string>
<string name="kg_login_instructions" msgid="1100551261265506448">"A feloldáshoz jelentkezzen be Google-fiókjával."</string>
- <string name="kg_login_username_hint" msgid="5718534272070920364">"Felhasználónév (e-mail cím)"</string>
+ <string name="kg_login_username_hint" msgid="5718534272070920364">"Felhasználónév (e-mail-cím)"</string>
<string name="kg_login_password_hint" msgid="9057289103827298549">"Jelszó"</string>
<string name="kg_login_submit_button" msgid="5355904582674054702">"Bejelentkezés"</string>
<string name="kg_login_invalid_input" msgid="5754664119319872197">"Érvénytelen felhasználónév vagy jelszó."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 936ba59..74d7c98 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -229,7 +229,7 @@
<string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakter"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"se kontaktene dine"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"Posisjon"</string>
- <string name="permgroupdesc_location" msgid="1346617465127855033">"tilgang til enhetens plassering"</string>
+ <string name="permgroupdesc_location" msgid="1346617465127855033">"få tilgang til enhetens plassering"</string>
<string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
<string name="permgroupdesc_calendar" msgid="3889615280211184106">"åpne kalenderen din"</string>
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 2e06a0e..9af1378b 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -358,7 +358,7 @@
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"accesează serviciul de apelare IMS"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite aplicației să folosească serviciul IMS pentru apeluri, fără intervenția dvs."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"citeşte starea și identitatea telefonului"</string>
- <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite aplicației să acceseze funcţiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanţă conectat printr-un apel."</string>
+ <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite aplicației să acceseze funcţiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanță conectat printr-un apel."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"împiedicarea computerului tablet PC să intre în repaus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"împiedică intrarea televizorului în stare de inactivitate"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"împiedicare intrare telefon în repaus"</string>
@@ -398,9 +398,9 @@
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar televizorul dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar telefonul dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă."</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"accesează setările Bluetooth"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite aplicației să configureze tableta Bluetooth locală, să descopere și să se împerecheze cu dispozitive la distanţă."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permite aplicației să configureze tableta Bluetooth locală, să descopere și să se împerecheze cu dispozitive la distanță."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"Permite aplicației să configureze televizorul Bluetooth local, precum și să descopere și să se asocieze cu dispozitive la distanță."</string>
- <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite aplicației să configureze telefonul Bluetooth local, să descopere și să se împerecheze cu dispozitive la distanţă."</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite aplicației să configureze telefonul Bluetooth local, să descopere și să se împerecheze cu dispozitive la distanță."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"se conectează și se deconectează de la WiMAX"</string>
<string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite aplicației să stabilească dacă o rețea WiMAX este activată și să vadă informațiile cu privire la toate reţelele WiMAX conectate."</string>
<string name="permlab_changeWimaxState" msgid="340465839241528618">"schimbaţi starea WiMAX"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 6e79f3d..b3c70a5 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -376,10 +376,10 @@
<string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"允许应用更改平板电脑的时区。"</string>
<string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"允许应用更改电视的时区。"</string>
<string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"允许应用更改手机的时区。"</string>
- <string name="permlab_getAccounts" msgid="1086795467760122114">"查找设备上的帐户"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"允许该应用获取平板电脑已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。"</string>
- <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"允许应用获取电视已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。"</string>
- <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"允许该应用获取手机已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。"</string>
+ <string name="permlab_getAccounts" msgid="1086795467760122114">"查找设备上的帐号"</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"允许该应用获取平板电脑已知的帐号列表,其中可能包括由已安装的应用创建的所有帐号。"</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"允许应用获取电视已知的帐号列表,其中可能包括由已安装的应用创建的所有帐号。"</string>
+ <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"允许该应用获取手机已知的帐号列表,其中可能包括由已安装的应用创建的所有帐号。"</string>
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"查看网络连接"</string>
<string name="permdesc_accessNetworkState" msgid="8318964424675960975">"允许该应用查看网络连接的相关信息,例如存在和连接的网络。"</string>
<string name="permlab_createNetworkSockets" msgid="7934516631384168107">"拥有完全的网络访问权限"</string>
@@ -436,11 +436,11 @@
</string-array>
<string name="fingerprint_icon_content_description" msgid="2340202869968465936">"指纹图标"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"读取同步设置"</string>
- <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允许该应用读取某个帐户的同步设置。例如,此权限可确定“联系人”应用是否与某个帐户同步。"</string>
+ <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允许该应用读取某个帐号的同步设置。例如,此权限可确定“联系人”应用是否与某个帐号同步。"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"启用和停用同步"</string>
- <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"允许该应用修改某个帐户的同步设置。例如,此权限可用于在“联系人”应用与某个帐户之间启用同步。"</string>
+ <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"允许该应用修改某个帐号的同步设置。例如,此权限可用于在“联系人”应用与某个帐号之间启用同步。"</string>
<string name="permlab_readSyncStats" msgid="7396577451360202448">"读取同步统计信息"</string>
- <string name="permdesc_readSyncStats" msgid="1510143761757606156">"允许该应用读取某个帐户的同步统计信息,包括同步活动历史记录和同步数据量。"</string>
+ <string name="permdesc_readSyncStats" msgid="1510143761757606156">"允许该应用读取某个帐号的同步统计信息,包括同步活动历史记录和同步数据量。"</string>
<string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"读取您的USB存储设备中的内容"</string>
<string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"读取您的SD卡中的内容"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"允许应用读取您USB存储设备中的内容。"</string>
@@ -696,9 +696,9 @@
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"您已经<xliff:g id="NUMBER">%d</xliff:g>次错误地尝试解锁手机。手机现在将恢复为出厂默认设置。"</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g>秒后重试。"</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"忘记了图案?"</string>
- <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"帐户解锁"</string>
+ <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"帐号解锁"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"图案尝试次数过多"</string>
- <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"要解除锁定,请使用您的Google帐户登录。"</string>
+ <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"要解除锁定,请使用您的Google帐号登录。"</string>
<string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"用户名(电子邮件)"</string>
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"密码"</string>
<string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"登录"</string>
@@ -1088,13 +1088,13 @@
<string name="ime_action_default" msgid="2840921885558045721">"执行"</string>
<string name="dial_number_using" msgid="5789176425167573586">"拨打电话\n<xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"创建电话号码为\n<xliff:g id="NUMBER">%s</xliff:g> 的联系人"</string>
- <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"以下一个或多个应用请求获得相应权限,以便在当前和以后访问您的帐户。"</string>
+ <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"以下一个或多个应用请求获得相应权限,以便在当前和以后访问您的帐号。"</string>
<string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"您是否同意此请求?"</string>
<string name="grant_permissions_header_text" msgid="6874497408201826708">"访问权限请求"</string>
<string name="allow" msgid="7225948811296386551">"允许"</string>
<string name="deny" msgid="2081879885755434506">"拒绝"</string>
<string name="permission_request_notification_title" msgid="6486759795926237907">"权限请求"</string>
- <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"应用对帐户 <xliff:g id="ACCOUNT">%s</xliff:g>\n 提出权限请求。"</string>
+ <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"应用对帐号 <xliff:g id="ACCOUNT">%s</xliff:g>\n 提出权限请求。"</string>
<string name="forward_intent_to_owner" msgid="1207197447013960896">"您目前是在工作资料之外使用此应用"</string>
<string name="forward_intent_to_work" msgid="621480743856004612">"您目前是在工作资料内使用此应用"</string>
<string name="input_method_binding_label" msgid="1283557179944992649">"输入法"</string>
@@ -1143,13 +1143,13 @@
<string name="gpsVerifYes" msgid="2346566072867213563">"是"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"否"</string>
<string name="sync_too_many_deletes" msgid="5296321850662746890">"超出删除限制"</string>
- <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"帐户 <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> 在进行“<xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>”同步时删除了 <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> 项内容。您要如何处理这些删除的内容?"</string>
+ <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"帐号 <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> 在进行“<xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>”同步时删除了 <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> 项内容。您要如何处理这些删除的内容?"</string>
<string name="sync_really_delete" msgid="2572600103122596243">"删除这些内容"</string>
<string name="sync_undo_deletes" msgid="2941317360600338602">"撤消删除"</string>
<string name="sync_do_nothing" msgid="3743764740430821845">"目前不进行任何操作"</string>
- <string name="choose_account_label" msgid="5655203089746423927">"选择帐户"</string>
- <string name="add_account_label" msgid="2935267344849993553">"添加帐户"</string>
- <string name="add_account_button_label" msgid="3611982894853435874">"添加帐户"</string>
+ <string name="choose_account_label" msgid="5655203089746423927">"选择帐号"</string>
+ <string name="add_account_label" msgid="2935267344849993553">"添加帐号"</string>
+ <string name="add_account_button_label" msgid="3611982894853435874">"添加帐号"</string>
<string name="number_picker_increment_button" msgid="2412072272832284313">"增大"</string>
<string name="number_picker_decrement_button" msgid="476050778386779067">"减小"</string>
<string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"触摸 <xliff:g id="VALUE">%s</xliff:g> 次并按住。"</string>
@@ -1276,13 +1276,13 @@
<string name="kg_invalid_puk" msgid="3638289409676051243">"请重新输入正确的PUK码。如果尝试错误次数过多,SIM卡将永久停用。"</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN码不匹配"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"图案尝试次数过多"</string>
- <string name="kg_login_instructions" msgid="1100551261265506448">"要解锁,请登录您的Google帐户。"</string>
+ <string name="kg_login_instructions" msgid="1100551261265506448">"要解锁,请登录您的Google帐号。"</string>
<string name="kg_login_username_hint" msgid="5718534272070920364">"用户名(电子邮件地址)"</string>
<string name="kg_login_password_hint" msgid="9057289103827298549">"密码"</string>
<string name="kg_login_submit_button" msgid="5355904582674054702">"登录"</string>
<string name="kg_login_invalid_input" msgid="5754664119319872197">"用户名或密码无效。"</string>
<string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"忘记了用户名或密码?\n请访问 "<b>"google.com/accounts/recovery"</b>"。"</string>
- <string name="kg_login_checking_password" msgid="1052685197710252395">"正在检查帐户…"</string>
+ <string name="kg_login_checking_password" msgid="1052685197710252395">"正在检查帐号…"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"您已经<xliff:g id="NUMBER_0">%1$d</xliff:g>次输错了PIN码。\n\n请在<xliff:g id="NUMBER_1">%2$d</xliff:g>秒后重试。"</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次输错密码。\n\n请在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒后重试。"</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。\n\n请在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒后重试。"</string>
@@ -1292,9 +1292,9 @@
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"您已经<xliff:g id="NUMBER">%d</xliff:g>次错误地尝试解锁平板电脑。平板电脑现在将恢复为出厂默认设置。"</string>
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁电视。电视现在将恢复为出厂默认设置。"</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"您已经<xliff:g id="NUMBER">%d</xliff:g>次错误地尝试解锁手机。手机现在将恢复为出厂默认设置。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用电子邮件帐户解锁电视。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用电子邮件帐号解锁电视。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"删除"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"要将音量调高到推荐水平以上吗?\n\n长时间保持高音量可能会损伤听力。"</string>
diff --git a/graphics/java/android/graphics/drawable/RippleComponent.java b/graphics/java/android/graphics/drawable/RippleComponent.java
index 2d378c6..e83513c 100644
--- a/graphics/java/android/graphics/drawable/RippleComponent.java
+++ b/graphics/java/android/graphics/drawable/RippleComponent.java
@@ -20,6 +20,7 @@
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
+import android.util.DisplayMetrics;
import android.view.DisplayListCanvas;
import android.view.RenderNodeAnimator;
@@ -50,7 +51,7 @@
protected float mTargetRadius;
/** Screen density used to adjust pixel-based constants. */
- protected float mDensity;
+ protected float mDensityScale;
/**
* If set, force all ripple animations to not run on RenderThread, even if it would be
@@ -71,7 +72,7 @@
}
}
- public final void setup(float maxRadius, float density) {
+ public final void setup(float maxRadius, int densityDpi) {
if (maxRadius >= 0) {
mHasMaxRadius = true;
mTargetRadius = maxRadius;
@@ -79,7 +80,7 @@
mTargetRadius = getTargetRadius(mBounds);
}
- mDensity = density;
+ mDensityScale = densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
onTargetRadiusChanged(mTargetRadius);
}
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 52e7f24..aaab529 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -160,7 +160,7 @@
private Paint mRipplePaint;
/** Target density of the display into which ripples are drawn. */
- private float mDensity = 1.0f;
+ private int mDensity;
/** Whether bounds are being overridden. */
private boolean mOverrideBounds;
@@ -544,8 +544,7 @@
mBackground = new RippleBackground(this, mHotspotBounds, mForceSoftware);
}
- final float densityScale = mState.mDensity * DisplayMetrics.DENSITY_DEFAULT_SCALE;
- mBackground.setup(mState.mMaxRadius, densityScale);
+ mBackground.setup(mState.mMaxRadius, mDensity);
mBackground.enter(focused);
}
diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java
index c660846..829733e 100644
--- a/graphics/java/android/graphics/drawable/RippleForeground.java
+++ b/graphics/java/android/graphics/drawable/RippleForeground.java
@@ -168,7 +168,7 @@
}
final int duration = (int)
- (1000 * Math.sqrt(mTargetRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5);
+ (1000 * Math.sqrt(mTargetRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensityScale) + 0.5);
final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1);
tweenRadius.setAutoCancel(true);
@@ -204,7 +204,7 @@
private int getRadiusExitDuration() {
final float remainingRadius = mTargetRadius - getCurrentRadius();
return (int) (1000 * Math.sqrt(remainingRadius / (WAVE_TOUCH_UP_ACCELERATION
- + WAVE_TOUCH_DOWN_ACCELERATION) * mDensity) + 0.5);
+ + WAVE_TOUCH_DOWN_ACCELERATION) * mDensityScale) + 0.5);
}
private float getCurrentRadius() {
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 9d3d4ae..5cdd723 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -64,6 +64,7 @@
PatchCache.cpp \
PathCache.cpp \
PathTessellator.cpp \
+ PathParser.cpp \
PixelBuffer.cpp \
Program.cpp \
ProgramCache.cpp \
@@ -82,6 +83,7 @@
TextDropShadowCache.cpp \
Texture.cpp \
TextureCache.cpp \
+ VectorDrawablePath.cpp \
protos/hwui.proto
hwui_cflags := \
@@ -213,6 +215,7 @@
unit_tests/FatVectorTests.cpp \
unit_tests/LayerUpdateQueueTests.cpp \
unit_tests/LinearAllocatorTests.cpp \
+ unit_tests/PathParserTests.cpp \
unit_tests/StringUtilsTests.cpp
ifeq (true, $(HWUI_NEW_OPS))
@@ -272,6 +275,7 @@
LOCAL_SRC_FILES += \
microbench/DisplayListCanvasBench.cpp \
microbench/LinearAllocatorBench.cpp \
+ microbench/PathParserBench.cpp \
microbench/ShadowBench.cpp
ifeq (true, $(HWUI_NEW_OPS))
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8c3603b..12c4607 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2255,12 +2255,15 @@
PathTexture* texture = mCaches.pathCache.get(path, paint);
if (!texture) return;
- const AutoTexture autoCleanup(texture);
const float x = texture->left - texture->offset;
const float y = texture->top - texture->offset;
drawPathTexture(texture, x, y, paint);
+
+ if (texture->cleanup) {
+ mCaches.pathCache.remove(path, paint);
+ }
mDirty = true;
}
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index fd9ab18..06ea55a 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -396,6 +396,13 @@
return texture;
}
+void PathCache::remove(const SkPath* path, const SkPaint* paint)
+{
+ PathDescription entry(kShapePath, paint);
+ entry.shape.path.mGenerationID = path->getGenerationID();
+ mCache.remove(entry);
+}
+
void PathCache::precache(const SkPath* path, const SkPaint* paint) {
if (!Caches::getInstance().tasks.canRunTasks()) {
return;
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 31f8d35..302e9f8 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -202,6 +202,7 @@
PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
bool useCenter, const SkPaint* paint);
PathTexture* get(const SkPath* path, const SkPaint* paint);
+ void remove(const SkPath* path, const SkPaint* paint);
/**
* Removes the specified path. This is meant to be called from threads
diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp
new file mode 100644
index 0000000..e8ed8a1
--- /dev/null
+++ b/libs/hwui/PathParser.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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 "PathParser.h"
+
+#include "jni.h"
+
+#include <utils/Log.h>
+#include <sstream>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace uirenderer {
+
+static size_t nextStart(const char* s, size_t length, size_t startIndex) {
+ size_t index = startIndex;
+ while (index < length) {
+ char c = s[index];
+ // Note that 'e' or 'E' are not valid path commands, but could be
+ // used for floating point numbers' scientific notation.
+ // Therefore, when searching for next command, we should ignore 'e'
+ // and 'E'.
+ if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
+ && c != 'e' && c != 'E') {
+ return index;
+ }
+ index++;
+ }
+ return index;
+}
+
+/**
+ * Calculate the position of the next comma or space or negative sign
+ * @param s the string to search
+ * @param start the position to start searching
+ * @param result the result of the extraction, including the position of the
+ * the starting position of next number, whether it is ending with a '-'.
+ */
+static void extract(int* outEndPosition, bool* outEndWithNegOrDot, const char* s, int start, int end) {
+ // Now looking for ' ', ',', '.' or '-' from the start.
+ int currentIndex = start;
+ bool foundSeparator = false;
+ *outEndWithNegOrDot = false;
+ bool secondDot = false;
+ bool isExponential = false;
+ for (; currentIndex < end; currentIndex++) {
+ bool isPrevExponential = isExponential;
+ isExponential = false;
+ char currentChar = s[currentIndex];
+ switch (currentChar) {
+ case ' ':
+ case ',':
+ foundSeparator = true;
+ break;
+ case '-':
+ // The negative sign following a 'e' or 'E' is not a separator.
+ if (currentIndex != start && !isPrevExponential) {
+ foundSeparator = true;
+ *outEndWithNegOrDot = true;
+ }
+ break;
+ case '.':
+ if (!secondDot) {
+ secondDot = true;
+ } else {
+ // This is the second dot, and it is considered as a separator.
+ foundSeparator = true;
+ *outEndWithNegOrDot = true;
+ }
+ break;
+ case 'e':
+ case 'E':
+ isExponential = true;
+ break;
+ }
+ if (foundSeparator) {
+ break;
+ }
+ }
+ // In the case where nothing is found, we put the end position to the end of
+ // our extract range. Otherwise, end position will be where separator is found.
+ *outEndPosition = currentIndex;
+}
+
+/**
+* Parse the floats in the string.
+* This is an optimized version of parseFloat(s.split(",|\\s"));
+*
+* @param s the string containing a command and list of floats
+* @return array of floats
+*/
+static void getFloats(std::vector<float>* outPoints, const char* pathStr, int start, int end) {
+
+ if (pathStr[start] == 'z' || pathStr[start] == 'Z') {
+ return;
+ }
+ int startPosition = start + 1;
+ int endPosition = start;
+
+ // The startPosition should always be the first character of the
+ // current number, and endPosition is the character after the current
+ // number.
+ while (startPosition < end) {
+ bool endWithNegOrDot;
+ extract(&endPosition, &endWithNegOrDot, pathStr, startPosition, end);
+
+ if (startPosition < endPosition) {
+ outPoints->push_back(strtof(&pathStr[startPosition], NULL));
+ }
+
+ if (endWithNegOrDot) {
+ // Keep the '-' or '.' sign with next number.
+ startPosition = endPosition;
+ } else {
+ startPosition = endPosition + 1;
+ }
+ }
+}
+
+void PathParser::getPathDataFromString(PathData* data, const char* pathStr, size_t strLen) {
+ if (pathStr == NULL) {
+ return;
+ }
+
+ size_t start = 0;
+ size_t end = 1;
+
+ while (end < strLen) {
+ end = nextStart(pathStr, strLen, end);
+ std::vector<float> points;
+ getFloats(&points, pathStr, start, end);
+ data->verbs.push_back(pathStr[start]);
+ data->verbSizes.push_back(points.size());
+ data->points.insert(data->points.end(), points.begin(), points.end());
+ start = end;
+ end++;
+ }
+
+ if ((end - start) == 1 && pathStr[start] != '\0') {
+ data->verbs.push_back(pathStr[start]);
+ data->verbSizes.push_back(0);
+ }
+
+ int i = 0;
+ while(pathStr[i] != '\0') {
+ i++;
+ }
+
+}
+
+void PathParser::dump(const PathData& data) {
+ // Print out the path data.
+ size_t start = 0;
+ for (size_t i = 0; i < data.verbs.size(); i++) {
+ std::ostringstream os;
+ os << data.verbs[i];
+ for (size_t j = 0; j < data.verbSizes[i]; j++) {
+ os << " " << data.points[start + j];
+ }
+ start += data.verbSizes[i];
+ ALOGD("%s", os.str().c_str());
+ }
+
+ std::ostringstream os;
+ for (size_t i = 0; i < data.points.size(); i++) {
+ os << data.points[i] << ", ";
+ }
+ ALOGD("points are : %s", os.str().c_str());
+}
+
+void PathParser::parseStringForSkPath(SkPath* skPath, const char* pathStr, size_t strLen) {
+ PathData pathData;
+ getPathDataFromString(&pathData, pathStr, strLen);
+ VectorDrawablePath::verbsToPath(skPath, &pathData);
+}
+
+}; // namespace uirenderer
+}; //namespace android
diff --git a/libs/hwui/PathParser.h b/libs/hwui/PathParser.h
new file mode 100644
index 0000000..6dc7ee1
--- /dev/null
+++ b/libs/hwui/PathParser.h
@@ -0,0 +1,37 @@
+/*
+ * 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 ANDROID_HWUI_PATHPARSER_H
+#define ANDROID_HWUI_PATHPARSER_H
+
+#include "VectorDrawablePath.h"
+
+#include <jni.h>
+#include <android/log.h>
+
+namespace android {
+namespace uirenderer {
+
+class PathParser {
+public:
+ static void parseStringForSkPath(SkPath* outPath, const char* pathStr, size_t strLength);
+ static void getPathDataFromString(PathData* outData, const char* pathStr, size_t strLength);
+ static void dump(const PathData& data);
+};
+
+}; // namespace uirenderer
+}; // namespace android
+#endif //ANDROID_HWUI_PATHPARSER_H
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index bdce73c..759e39b 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -741,7 +741,7 @@
// vertex's location.
int newPenumbraNumber = indexDelta - 1;
- float accumulatedDeltaLength[newPenumbraNumber];
+ float accumulatedDeltaLength[indexDelta];
float totalDeltaLength = 0;
// To save time, cache the previous umbra vertex info outside the loop
diff --git a/libs/hwui/VectorDrawablePath.cpp b/libs/hwui/VectorDrawablePath.cpp
new file mode 100644
index 0000000..115435c
--- /dev/null
+++ b/libs/hwui/VectorDrawablePath.cpp
@@ -0,0 +1,496 @@
+/*
+ * 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 "VectorDrawablePath.h"
+
+#include "PathParser.h"
+
+#include <math.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace uirenderer {
+
+class PathResolver {
+public:
+ float currentX = 0;
+ float currentY = 0;
+ float ctrlPointX = 0;
+ float ctrlPointY = 0;
+ float currentSegmentStartX = 0;
+ float currentSegmentStartY = 0;
+ void addCommand(SkPath* outPath, char previousCmd,
+ char cmd, const std::vector<float>* points, size_t start, size_t end);
+};
+
+VectorDrawablePath::VectorDrawablePath(const char* pathStr, size_t strLength) {
+ PathParser::getPathDataFromString(&mData, pathStr, strLength);
+ verbsToPath(&mSkPath, &mData);
+}
+
+VectorDrawablePath::VectorDrawablePath(const PathData& data) {
+ mData = data;
+ // Now we need to construct a path
+ verbsToPath(&mSkPath, &data);
+}
+
+VectorDrawablePath::VectorDrawablePath(const VectorDrawablePath& path) {
+ mData = path.mData;
+ verbsToPath(&mSkPath, &mData);
+}
+
+bool VectorDrawablePath::canMorph(const PathData& morphTo) {
+ if (mData.verbs.size() != morphTo.verbs.size()) {
+ return false;
+ }
+
+ for (unsigned int i = 0; i < mData.verbs.size(); i++) {
+ if (mData.verbs[i] != morphTo.verbs[i]
+ || mData.verbSizes[i] != morphTo.verbSizes[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VectorDrawablePath::canMorph(const VectorDrawablePath& path) {
+ return canMorph(path.mData);
+}
+ /**
+ * Convert an array of PathVerb to Path.
+ */
+void VectorDrawablePath::verbsToPath(SkPath* outPath, const PathData* data) {
+ PathResolver resolver;
+ char previousCommand = 'm';
+ size_t start = 0;
+ outPath->reset();
+ for (unsigned int i = 0; i < data->verbs.size(); i++) {
+ size_t verbSize = data->verbSizes[i];
+ resolver.addCommand(outPath, previousCommand, data->verbs[i], &data->points, start,
+ start + verbSize - 1u);
+ previousCommand = data->verbs[i];
+ start += verbSize;
+ }
+}
+
+/**
+ * The current PathVerb will be interpolated between the
+ * <code>nodeFrom</code> and <code>nodeTo</code> according to the
+ * <code>fraction</code>.
+ *
+ * @param nodeFrom The start value as a PathVerb.
+ * @param nodeTo The end value as a PathVerb
+ * @param fraction The fraction to interpolate.
+ */
+void VectorDrawablePath::interpolatePaths(PathData* outData,
+ const PathData* from, const PathData* to, float fraction) {
+ outData->points.resize(from->points.size());
+ outData->verbSizes = from->verbSizes;
+ outData->verbs = from->verbs;
+
+ for (size_t i = 0; i < from->points.size(); i++) {
+ outData->points[i] = from->points[i] * (1 - fraction) + to->points[i] * fraction;
+ }
+}
+
+/**
+ * Converts an arc to cubic Bezier segments and records them in p.
+ *
+ * @param p The target for the cubic Bezier segments
+ * @param cx The x coordinate center of the ellipse
+ * @param cy The y coordinate center of the ellipse
+ * @param a The radius of the ellipse in the horizontal direction
+ * @param b The radius of the ellipse in the vertical direction
+ * @param e1x E(eta1) x coordinate of the starting point of the arc
+ * @param e1y E(eta2) y coordinate of the starting point of the arc
+ * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
+ * @param start The start angle of the arc on the ellipse
+ * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
+ */
+static void arcToBezier(SkPath* p,
+ double cx,
+ double cy,
+ double a,
+ double b,
+ double e1x,
+ double e1y,
+ double theta,
+ double start,
+ double sweep) {
+ // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
+ // and http://www.spaceroots.org/documents/ellipse/node22.html
+
+ // Maximum of 45 degrees per cubic Bezier segment
+ int numSegments = ceil(fabs(sweep * 4 / M_PI));
+
+ double eta1 = start;
+ double cosTheta = cos(theta);
+ double sinTheta = sin(theta);
+ double cosEta1 = cos(eta1);
+ double sinEta1 = sin(eta1);
+ double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
+ double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
+
+ double anglePerSegment = sweep / numSegments;
+ for (int i = 0; i < numSegments; i++) {
+ double eta2 = eta1 + anglePerSegment;
+ double sinEta2 = sin(eta2);
+ double cosEta2 = cos(eta2);
+ double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
+ double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
+ double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
+ double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
+ double tanDiff2 = tan((eta2 - eta1) / 2);
+ double alpha =
+ sin(eta2 - eta1) * (sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
+ double q1x = e1x + alpha * ep1x;
+ double q1y = e1y + alpha * ep1y;
+ double q2x = e2x - alpha * ep2x;
+ double q2y = e2y - alpha * ep2y;
+
+ p->cubicTo((float) q1x,
+ (float) q1y,
+ (float) q2x,
+ (float) q2y,
+ (float) e2x,
+ (float) e2y);
+ eta1 = eta2;
+ e1x = e2x;
+ e1y = e2y;
+ ep1x = ep2x;
+ ep1y = ep2y;
+ }
+}
+
+inline double toRadians(float theta) { return theta * M_PI / 180;}
+
+static void drawArc(SkPath* p,
+ float x0,
+ float y0,
+ float x1,
+ float y1,
+ float a,
+ float b,
+ float theta,
+ bool isMoreThanHalf,
+ bool isPositiveArc) {
+
+ /* Convert rotation angle from degrees to radians */
+ double thetaD = toRadians(theta);
+ /* Pre-compute rotation matrix entries */
+ double cosTheta = cos(thetaD);
+ double sinTheta = sin(thetaD);
+ /* Transform (x0, y0) and (x1, y1) into unit space */
+ /* using (inverse) rotation, followed by (inverse) scale */
+ double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
+ double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
+ double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
+ double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
+
+ /* Compute differences and averages */
+ double dx = x0p - x1p;
+ double dy = y0p - y1p;
+ double xm = (x0p + x1p) / 2;
+ double ym = (y0p + y1p) / 2;
+ /* Solve for intersecting unit circles */
+ double dsq = dx * dx + dy * dy;
+ if (dsq == 0.0) {
+ ALOGW("Points are coincident");
+ return; /* Points are coincident */
+ }
+ double disc = 1.0 / dsq - 1.0 / 4.0;
+ if (disc < 0.0) {
+ ALOGW("Points are too far apart %f", dsq);
+ float adjust = (float) (sqrt(dsq) / 1.99999);
+ drawArc(p, x0, y0, x1, y1, a * adjust,
+ b * adjust, theta, isMoreThanHalf, isPositiveArc);
+ return; /* Points are too far apart */
+ }
+ double s = sqrt(disc);
+ double sdx = s * dx;
+ double sdy = s * dy;
+ double cx;
+ double cy;
+ if (isMoreThanHalf == isPositiveArc) {
+ cx = xm - sdy;
+ cy = ym + sdx;
+ } else {
+ cx = xm + sdy;
+ cy = ym - sdx;
+ }
+
+ double eta0 = atan2((y0p - cy), (x0p - cx));
+
+ double eta1 = atan2((y1p - cy), (x1p - cx));
+
+ double sweep = (eta1 - eta0);
+ if (isPositiveArc != (sweep >= 0)) {
+ if (sweep > 0) {
+ sweep -= 2 * M_PI;
+ } else {
+ sweep += 2 * M_PI;
+ }
+ }
+
+ cx *= a;
+ cy *= b;
+ double tcx = cx;
+ cx = cx * cosTheta - cy * sinTheta;
+ cy = tcx * sinTheta + cy * cosTheta;
+
+ arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
+}
+
+
+void PathResolver::addCommand(SkPath* outPath, char previousCmd,
+ char cmd, const std::vector<float>* points, size_t start, size_t end) {
+
+ int incr = 2;
+ float reflectiveCtrlPointX;
+ float reflectiveCtrlPointY;
+
+ switch (cmd) {
+ case 'z':
+ case 'Z':
+ outPath->close();
+ // Path is closed here, but we need to move the pen to the
+ // closed position. So we cache the segment's starting position,
+ // and restore it here.
+ currentX = currentSegmentStartX;
+ currentY = currentSegmentStartY;
+ ctrlPointX = currentSegmentStartX;
+ ctrlPointY = currentSegmentStartY;
+ outPath->moveTo(currentX, currentY);
+ break;
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ incr = 2;
+ break;
+ case 'h':
+ case 'H':
+ case 'v':
+ case 'V':
+ incr = 1;
+ break;
+ case 'c':
+ case 'C':
+ incr = 6;
+ break;
+ case 's':
+ case 'S':
+ case 'q':
+ case 'Q':
+ incr = 4;
+ break;
+ case 'a':
+ case 'A':
+ incr = 7;
+ break;
+ }
+
+ for (unsigned int k = start; k <= end; k += incr) {
+ switch (cmd) {
+ case 'm': // moveto - Start a new sub-path (relative)
+ currentX += points->at(k + 0);
+ currentY += points->at(k + 1);
+ if (k > start) {
+ // According to the spec, if a moveto is followed by multiple
+ // pairs of coordinates, the subsequent pairs are treated as
+ // implicit lineto commands.
+ outPath->rLineTo(points->at(k + 0), points->at(k + 1));
+ } else {
+ outPath->rMoveTo(points->at(k + 0), points->at(k + 1));
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
+ }
+ break;
+ case 'M': // moveto - Start a new sub-path
+ currentX = points->at(k + 0);
+ currentY = points->at(k + 1);
+ if (k > start) {
+ // According to the spec, if a moveto is followed by multiple
+ // pairs of coordinates, the subsequent pairs are treated as
+ // implicit lineto commands.
+ outPath->lineTo(points->at(k + 0), points->at(k + 1));
+ } else {
+ outPath->moveTo(points->at(k + 0), points->at(k + 1));
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
+ }
+ break;
+ case 'l': // lineto - Draw a line from the current point (relative)
+ outPath->rLineTo(points->at(k + 0), points->at(k + 1));
+ currentX += points->at(k + 0);
+ currentY += points->at(k + 1);
+ break;
+ case 'L': // lineto - Draw a line from the current point
+ outPath->lineTo(points->at(k + 0), points->at(k + 1));
+ currentX = points->at(k + 0);
+ currentY = points->at(k + 1);
+ break;
+ case 'h': // horizontal lineto - Draws a horizontal line (relative)
+ outPath->rLineTo(points->at(k + 0), 0);
+ currentX += points->at(k + 0);
+ break;
+ case 'H': // horizontal lineto - Draws a horizontal line
+ outPath->lineTo(points->at(k + 0), currentY);
+ currentX = points->at(k + 0);
+ break;
+ case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+ outPath->rLineTo(0, points->at(k + 0));
+ currentY += points->at(k + 0);
+ break;
+ case 'V': // vertical lineto - Draws a vertical line from the current point
+ outPath->lineTo(currentX, points->at(k + 0));
+ currentY = points->at(k + 0);
+ break;
+ case 'c': // curveto - Draws a cubic Bézier curve (relative)
+ outPath->rCubicTo(points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3),
+ points->at(k + 4), points->at(k + 5));
+
+ ctrlPointX = currentX + points->at(k + 2);
+ ctrlPointY = currentY + points->at(k + 3);
+ currentX += points->at(k + 4);
+ currentY += points->at(k + 5);
+
+ break;
+ case 'C': // curveto - Draws a cubic Bézier curve
+ outPath->cubicTo(points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3),
+ points->at(k + 4), points->at(k + 5));
+ currentX = points->at(k + 4);
+ currentY = points->at(k + 5);
+ ctrlPointX = points->at(k + 2);
+ ctrlPointY = points->at(k + 3);
+ break;
+ case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ outPath->rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ points->at(k + 0), points->at(k + 1),
+ points->at(k + 2), points->at(k + 3));
+ ctrlPointX = currentX + points->at(k + 0);
+ ctrlPointY = currentY + points->at(k + 1);
+ currentX += points->at(k + 2);
+ currentY += points->at(k + 3);
+ break;
+ case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ outPath->cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3));
+ ctrlPointX = points->at(k + 0);
+ ctrlPointY = points->at(k + 1);
+ currentX = points->at(k + 2);
+ currentY = points->at(k + 3);
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ outPath->rQuadTo(points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3));
+ ctrlPointX = currentX + points->at(k + 0);
+ ctrlPointY = currentY + points->at(k + 1);
+ currentX += points->at(k + 2);
+ currentY += points->at(k + 3);
+ break;
+ case 'Q': // Draws a quadratic Bézier
+ outPath->quadTo(points->at(k + 0), points->at(k + 1), points->at(k + 2), points->at(k + 3));
+ ctrlPointX = points->at(k + 0);
+ ctrlPointY = points->at(k + 1);
+ currentX = points->at(k + 2);
+ currentY = points->at(k + 3);
+ break;
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ outPath->rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ points->at(k + 0), points->at(k + 1));
+ ctrlPointX = currentX + reflectiveCtrlPointX;
+ ctrlPointY = currentY + reflectiveCtrlPointY;
+ currentX += points->at(k + 0);
+ currentY += points->at(k + 1);
+ break;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ outPath->quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ points->at(k + 0), points->at(k + 1));
+ ctrlPointX = reflectiveCtrlPointX;
+ ctrlPointY = reflectiveCtrlPointY;
+ currentX = points->at(k + 0);
+ currentY = points->at(k + 1);
+ break;
+ case 'a': // Draws an elliptical arc
+ // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
+ drawArc(outPath,
+ currentX,
+ currentY,
+ points->at(k + 5) + currentX,
+ points->at(k + 6) + currentY,
+ points->at(k + 0),
+ points->at(k + 1),
+ points->at(k + 2),
+ points->at(k + 3) != 0,
+ points->at(k + 4) != 0);
+ currentX += points->at(k + 5);
+ currentY += points->at(k + 6);
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ case 'A': // Draws an elliptical arc
+ drawArc(outPath,
+ currentX,
+ currentY,
+ points->at(k + 5),
+ points->at(k + 6),
+ points->at(k + 0),
+ points->at(k + 1),
+ points->at(k + 2),
+ points->at(k + 3) != 0,
+ points->at(k + 4) != 0);
+ currentX = points->at(k + 5);
+ currentY = points->at(k + 6);
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ }
+ previousCmd = cmd;
+ }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/VectorDrawablePath.h b/libs/hwui/VectorDrawablePath.h
new file mode 100644
index 0000000..40ce986
--- /dev/null
+++ b/libs/hwui/VectorDrawablePath.h
@@ -0,0 +1,58 @@
+/*
+ * 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 ANDROID_HWUI_VPATH_H
+#define ANDROID_HWUI_VPATH_H
+
+#include "SkPath.h"
+#include <vector>
+
+namespace android {
+namespace uirenderer {
+
+
+
+struct PathData {
+ // TODO: Try using FatVector instead of std::vector and do a micro benchmark on the performance
+ // difference.
+ std::vector<char> verbs;
+ std::vector<size_t> verbSizes;
+ std::vector<float> points;
+ bool operator== (const PathData& data) const {
+ return verbs == data.verbs && verbSizes == data.verbSizes && points == data.points;
+ }
+
+};
+
+class VectorDrawablePath {
+public:
+ VectorDrawablePath(const PathData& nodes);
+ VectorDrawablePath(const VectorDrawablePath& path);
+ VectorDrawablePath(const char* path, size_t strLength);
+ bool canMorph(const PathData& path);
+ bool canMorph(const VectorDrawablePath& path);
+ static void verbsToPath(SkPath* outPath, const PathData* data);
+ static void interpolatePaths(PathData* outPathData, const PathData* from, const PathData* to,
+ float fraction);
+private:
+ PathData mData;
+ SkPath mSkPath;
+};
+
+} // namespace uirenderer
+} // namespace android
+
+#endif // ANDROID_HWUI_VPATH_H
diff --git a/libs/hwui/microbench/PathParserBench.cpp b/libs/hwui/microbench/PathParserBench.cpp
new file mode 100644
index 0000000..198035e
--- /dev/null
+++ b/libs/hwui/microbench/PathParserBench.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 <benchmark/Benchmark.h>
+
+#include "PathParser.h"
+
+#include <SkPath.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+BENCHMARK_NO_ARG(BM_PathParser_parseStringPath);
+void BM_PathParser_parseStringPath::Run(int iter) {
+ const char* pathString = "M 1 1 m 2 2, l 3 3 L 3 3 H 4 h4 V5 v5, Q6 6 6 6 q 6 6 6 6t 7 7 T 7 7 C 8 8 8 8 8 8 c 8 8 8 8 8 8 S 9 9 9 9 s 9 9 9 9 A 10 10 0 1 1 10 10 a 10 10 0 1 1 10 10";
+ SkPath skPath;
+ size_t length = strlen(pathString);
+ StartBenchmarkTiming();
+ for (int i = 0; i < iter; i++) {
+ PathParser::parseStringForSkPath(&skPath, pathString, length);
+ }
+ StopBenchmarkTiming();
+}
diff --git a/libs/hwui/microbench/how_to_run.txt b/libs/hwui/microbench/how_to_run.txt
new file mode 100755
index 0000000..e6f80b2
--- /dev/null
+++ b/libs/hwui/microbench/how_to_run.txt
@@ -0,0 +1,4 @@
+mmm -j8 frameworks/base/libs/hwui &&
+adb push $ANDROID_PRODUCT_OUT/data/local/tmp/hwuimicro \
+ /data/local/tmp/hwuimicro &&
+ adb shell /data/local/tmp/hwuimicro
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index a1107f0..15ccd6a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -563,7 +563,10 @@
void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
void* retval;
task->setReturnPtr(&retval);
- mRenderThread.queueAndWait(task);
+ SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
+ AutoMutex _lock(mSyncMutex);
+ mRenderThread.queue(&syncTask);
+ mSyncCondition.wait(mSyncMutex);
return retval;
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d0e601e..338fab6 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -117,6 +117,9 @@
DrawFrameTask mDrawFrameTask;
+ Mutex mSyncMutex;
+ Condition mSyncCondition;
+
void destroyContext();
void post(RenderTask* task);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 526a848..9fb30c9 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -25,7 +25,9 @@
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <sys/resource.h>
+#include <utils/Condition.h>
#include <utils/Log.h>
+#include <utils/Mutex.h>
namespace android {
namespace uirenderer {
@@ -325,10 +327,16 @@
}
void RenderThread::queueAndWait(RenderTask* task) {
- SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
- AutoMutex _lock(mSyncMutex);
+ // These need to be local to the thread to avoid the Condition
+ // signaling the wrong thread. The easiest way to achieve that is to just
+ // make this on the stack, although that has a slight cost to it
+ Mutex mutex;
+ Condition condition;
+ SignalingRenderTask syncTask(task, &mutex, &condition);
+
+ AutoMutex _lock(mutex);
queue(&syncTask);
- mSyncCondition.wait(mSyncMutex);
+ condition.wait(mutex);
}
void RenderThread::queueAtFront(RenderTask* task) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index d8c7e61..076e3d4 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -27,9 +27,7 @@
#include <utils/Looper.h>
#include <utils/Thread.h>
-#include <condition_variable>
#include <memory>
-#include <mutex>
#include <set>
namespace android {
@@ -127,8 +125,6 @@
nsecs_t mNextWakeup;
TaskQueue mQueue;
- Mutex mSyncMutex;
- Condition mSyncCondition;
DisplayInfo mDisplayInfo;
diff --git a/libs/hwui/unit_tests/PathParserTests.cpp b/libs/hwui/unit_tests/PathParserTests.cpp
new file mode 100644
index 0000000..244bd6c
--- /dev/null
+++ b/libs/hwui/unit_tests/PathParserTests.cpp
@@ -0,0 +1,172 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "PathParser.h"
+#include "VectorDrawablePath.h"
+
+#include <functional>
+
+namespace android {
+namespace uirenderer {
+
+struct TestData {
+ const char* pathString;
+ const PathData pathData;
+ const std::function<void(SkPath*)> skPathLamda;
+};
+
+static TestData testData1 {
+ // Path
+ "M2.000000,22.000000l20.000000,0.000000 1e0-2e3z",
+ {
+ // Verbs
+ {'M', 'l', 'z'},
+ // Verb sizes
+ {2, 4, 0},
+ // Points
+ {2, 22, 20, 0, 1, -2000},
+ },
+ [](SkPath* outPath) {
+ outPath->moveTo(2, 22);
+ outPath->rLineTo(20, 0);
+ outPath->rLineTo(1, -2000);
+ outPath->close();
+ outPath->moveTo(2, 22);
+ }
+};
+
+static TestData testData2 {
+ // Path
+ "M 1 1 m 2 2, l 3 3 L 3 3 H 4 h4 V5 v5, Q6 6 6 6 q 6 6 6 6t 7 7 T 7 7 C 8 8 8 8 8 8 c 8 8 8 8 8 8 S 9 9 9 9 s 9 9 9 9 A 10 10 0 1 1 10 10 a 10 10 0 1 1 10 10",
+ {
+ // Verbs
+ {'M', 'm', 'l', 'L', 'H', 'h', 'V', 'v', 'Q', 'q', 't', 'T', 'C', 'c', 'S', 's', 'A', 'a'},
+ // VerbSizes
+ {2, 2, 2, 2, 1, 1, 1, 1, 4, 4, 2, 2, 6, 6, 4, 4, 7, 7},
+ // Points
+ {1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 5.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 10.0, 10.0, 0.0, 1.0, 1.0, 10.0, 10.0, 10.0, 10.0, 0.0, 1.0, 1.0, 10.0, 10.0, }
+ },
+ [](SkPath* outPath) {
+ outPath->moveTo(1.0, 1.0);
+ outPath->rMoveTo(2.0, 2.0);
+ outPath->rLineTo(3.0, 3.0);
+ outPath->lineTo(3.0, 3.0);
+ outPath->lineTo(4.0, 3.0);
+ outPath->rLineTo(4.0, 0);
+ outPath->lineTo(8.0, 5.0);
+ outPath->rLineTo(0, 5.0);
+ outPath->quadTo(6.0, 6.0, 6.0, 6.0);
+ outPath->rQuadTo(6.0, 6.0, 6.0, 6.0);
+ outPath->rQuadTo(0.0, 0.0, 7.0, 7.0);
+ outPath->quadTo(26.0, 26.0, 7.0, 7.0);
+ outPath->cubicTo(8.0, 8.0, 8.0, 8.0, 8.0, 8.0);
+ outPath->rCubicTo(8.0, 8.0, 8.0, 8.0, 8.0, 8.0);
+ outPath->cubicTo(16.0, 16.0, 9.0, 9.0, 9.0, 9.0);
+ outPath->rCubicTo(0.0, 0.0, 9.0, 9.0, 9.0, 9.0);
+ outPath->cubicTo(18.447775037328352, 20.404243860300607, 17.998389141249767, 22.8911717921705, 16.737515350332117, 24.986664170401575);
+ outPath->cubicTo(15.476641559414468, 27.08215654863265, 13.489843598291483, 28.644011882390082, 11.155893964798905, 29.37447073281729);
+ outPath->cubicTo(8.821944331306327, 30.1049295832445, 6.299226382436471, 29.954422532383525, 4.0686829203897235, 28.951642951534332);
+ outPath->cubicTo(1.838139458342976, 27.94886337068514, 0.05113662931485696, 26.161860541657013, -0.9516429515343354, 23.931317079610267);
+ outPath->cubicTo(-1.9544225323835278, 21.70077361756352, -2.1049295832444987, 19.178055668693663, -1.37447073281729, 16.844106035201087);
+ outPath->cubicTo(-0.6440118823900814, 14.51015640170851, 0.9178434513673546, 12.523358440585524, 3.0133358295984305, 11.262484649667876);
+ outPath->cubicTo(5.108828207829506, 10.001610858750228, 7.5957561396993984, 9.552224962671648, 10.000000000000005, 10.0);
+ outPath->cubicTo(10.0, 7.348852265086975, 11.054287646850167, 4.803576729418881, 12.928932188134523, 2.9289321881345254);
+ outPath->cubicTo(14.803576729418879, 1.0542876468501696, 17.348852265086972, 4.870079381441987E-16, 19.999999999999996, 0.0);
+ outPath->cubicTo(22.65114773491302, -4.870079381441987E-16, 25.19642327058112, 1.0542876468501678, 27.071067811865476, 2.9289321881345227);
+ outPath->cubicTo(28.94571235314983, 4.803576729418878, 30.0, 7.348852265086974, 30.0, 9.999999999999998);
+ outPath->cubicTo(30.0, 12.651147734913023, 28.94571235314983, 15.19642327058112, 27.071067811865476, 17.071067811865476);
+ outPath->cubicTo(25.19642327058112, 18.94571235314983, 22.651147734913028, 20.0, 20.000000000000004, 20.0);
+ }
+};
+
+static TestData testData3 {
+ // Path
+ "M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,-1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8 -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0 -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z",
+ {
+ // Verbs
+ {'M', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'C', 'z'},
+ // Verb sizes
+ {2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0},
+ // Points
+ {5.3, 13.2, -0.1, 0, -0.3, 0, -0.4, -0.1, -0.3, -0.2, -0.4, -0.7, -0.2, -1, 1.3, -1.9, 2.9, -3.4, 4.9, -4.5, 4.1, -2.2, 9.3, -2.2, 13.4, 0, 1.9, 1.1, 3.6, 2.5, 4.9, 4.4, 0.2, 0.3, 0.1, 0.8, -0.2, 1, -0.3, 0.2, -0.8, 0.1, -1, -0.2, -1.2, -1.7, -2.6, -3, -4.3, -4, -3.7, -2, -8.3, -2, -12, 0, -1.7, 0.9, -3.2, 2.3, -4.3, 4, 5.7, 13.1, 5.5, 13.2, 5.3, 13.2},
+ },
+ [](SkPath* outPath) {
+ outPath->moveTo(5.3, 13.2);
+ outPath->rCubicTo(-0.1, 0.0, -0.3, 0.0, -0.4, -0.1);
+ outPath->rCubicTo(-0.3, -0.2, -0.4, -0.7, -0.2, -1.0);
+ outPath->rCubicTo(1.3, -1.9, 2.9, -3.4, 4.9, -4.5);
+ outPath->rCubicTo(4.1, -2.2, 9.3, -2.2, 13.4, 0.0);
+ outPath->rCubicTo(1.9, 1.1, 3.6, 2.5, 4.9, 4.4);
+ outPath->rCubicTo(0.2, 0.3, 0.1, 0.8, -0.2, 1.0);
+ outPath->rCubicTo(-0.3, 0.2, -0.8, 0.1, -1.0, -0.2);
+ outPath->rCubicTo(-1.2, -1.7, -2.6, -3.0, -4.3, -4.0);
+ outPath->rCubicTo(-3.7, -2.0, -8.3, -2.0, -12.0, 0.0);
+ outPath->rCubicTo(-1.7, 0.9, -3.2, 2.3, -4.3, 4.0);
+ outPath->cubicTo(5.7, 13.1, 5.5, 13.2, 5.3, 13.2);
+ outPath->close();
+ outPath->moveTo(5.3, 13.2);
+ }
+};
+
+static TestData testData4 {
+ // Path
+ "l0.0.0.5.0.0.5-0.5.0.0-.5z",
+ {
+ // Verbs
+ {'l', 'z'},
+ // Verb sizes
+ {10, 0},
+ // Points
+ {0, 0, 0.5, 0, 0, 0.5, -0.5, 0, 0, -0.5},
+ },
+ [](SkPath* outPath) {
+ outPath->rLineTo(0.0, 0.0);
+ outPath->rLineTo(0.5, 0.0);
+ outPath->rLineTo(0.0, 0.5);
+ outPath->rLineTo(-0.5, 0.0);
+ outPath->rLineTo(0.0, -0.5);
+ outPath->close();
+ outPath->moveTo(0.0, 0.0);
+ }
+};
+
+const static TestData testDataSet[] = {testData1, testData2, testData3, testData4};
+
+TEST(PathPaser, parseString) {
+
+ for (int i = 0; i < 4; i++) {
+ // Test generated path data against the given data.
+ PathData pathData;
+ TestData testData = testDataSet[i];
+ size_t length = strlen(testData.pathString);
+ PathParser::getPathDataFromString(&pathData, testData.pathString, length);
+ PathParser::dump(pathData);
+ EXPECT_EQ(testData.pathData, pathData);
+
+ // Test SkPath generated
+ SkPath expectedPath;
+ testData.skPathLamda(&expectedPath);
+ SkPath actualPath;
+ VectorDrawablePath::verbsToPath(&actualPath, &pathData);
+ EXPECT_EQ(expectedPath, actualPath);
+ }
+
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/FatVector.h b/libs/hwui/utils/FatVector.h
index 315c249..93d37c2 100644
--- a/libs/hwui/utils/FatVector.h
+++ b/libs/hwui/utils/FatVector.h
@@ -29,6 +29,7 @@
#include "utils/Macros.h"
#include <stddef.h>
+#include <stdlib.h>
#include <type_traits>
#include <utils/Log.h>
@@ -95,6 +96,7 @@
FatVector(size_t capacity) : FatVector() {
this->resize(capacity);
}
+
private:
typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
};
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index e8f680f..49b579c 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -834,29 +834,36 @@
env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
CHECK(constructID != NULL);
- jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
+ const char *defaultMsg = "Unknown Error";
/* translate OS errors to Java API CryptoException errorCodes (which are positive) */
switch (err) {
case ERROR_DRM_NO_LICENSE:
err = gCryptoErrorCodes.cryptoErrorNoKey;
+ defaultMsg = "Crypto key not available";
break;
case ERROR_DRM_LICENSE_EXPIRED:
err = gCryptoErrorCodes.cryptoErrorKeyExpired;
+ defaultMsg = "License expired";
break;
case ERROR_DRM_RESOURCE_BUSY:
err = gCryptoErrorCodes.cryptoErrorResourceBusy;
+ defaultMsg = "Resource busy or unavailable";
break;
case ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
err = gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection;
+ defaultMsg = "Required output protections are not active";
break;
case ERROR_DRM_SESSION_NOT_OPENED:
err = gCryptoErrorCodes.cryptoErrorSessionNotOpened;
+ defaultMsg = "Attempted to use a closed session";
break;
default: /* Other negative DRM error codes go out as is. */
break;
}
+ jstring msgObj = env->NewStringUTF(msg != NULL ? msg : defaultMsg);
+
jthrowable exception =
(jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
diff --git a/packages/DocumentsUI/res/color/item_doc_grid_overlay.xml b/packages/DocumentsUI/res/color/item_doc_grid_overlay.xml
deleted file mode 100644
index bf19d4e..0000000
--- a/packages/DocumentsUI/res/color/item_doc_grid_overlay.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_activated="true"
- android:color="?android:attr/colorAccent"
- android:alpha="0.1" />
- <item
- android:state_enabled="false"
- android:color="?android:attr/colorBackground"
- android:alpha="0.5" />
- <item
- android:color="@android:color/transparent" />
-</selector>
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_grid_selection_check.png b/packages/DocumentsUI/res/drawable-hdpi/ic_grid_selection_check.png
deleted file mode 100644
index f3007c2..0000000
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_grid_selection_check.png
+++ /dev/null
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_grid_selection_check.png b/packages/DocumentsUI/res/drawable-mdpi/ic_grid_selection_check.png
deleted file mode 100644
index 16f2ab9..0000000
--- a/packages/DocumentsUI/res/drawable-mdpi/ic_grid_selection_check.png
+++ /dev/null
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_grid_selection_check.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_grid_selection_check.png
deleted file mode 100644
index 0885320..0000000
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_grid_selection_check.png
+++ /dev/null
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_grid_selection_check.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_grid_selection_check.png
deleted file mode 100644
index 083bbcc..0000000
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_grid_selection_check.png
+++ /dev/null
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_grid_selection_check.png b/packages/DocumentsUI/res/drawable-xxxhdpi/ic_grid_selection_check.png
deleted file mode 100644
index 74b1ca5..0000000
--- a/packages/DocumentsUI/res/drawable-xxxhdpi/ic_grid_selection_check.png
+++ /dev/null
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable/item_doc_grid_overlay.xml b/packages/DocumentsUI/res/drawable/item_doc_grid_overlay.xml
deleted file mode 100644
index 3f50fb9..0000000
--- a/packages/DocumentsUI/res/drawable/item_doc_grid_overlay.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/item_doc_grid_overlay" />
-</shape>
diff --git a/packages/DocumentsUI/res/drawable/item_doc_grid_overlay_icon.xml b/packages/DocumentsUI/res/drawable/item_doc_grid_overlay_icon.xml
deleted file mode 100644
index d40de1e..0000000
--- a/packages/DocumentsUI/res/drawable/item_doc_grid_overlay_icon.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="true">
- <item android:state_focused="true" android:state_activated="true" android:drawable="@drawable/ic_grid_selection_check" />
- <item android:state_focused="false" android:state_activated="true" android:drawable="@drawable/ic_grid_selection_check" />
- <item android:drawable="@android:color/transparent" />
-</selector>
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index 15b12ce..1dfb34a 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -14,132 +14,110 @@
limitations under the License.
-->
-<com.android.documentsui.GridItem xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="@dimen/grid_item_height"
+ android:layout_height="wrap_content"
android:layout_margin="@dimen/grid_item_margin"
android:background="@color/item_doc_grid_background"
android:focusable="true">
- <ImageView
- android:id="@+id/icon_thumb"
+ <!-- Main item thumbnail. Comprised of two overlapping images, the
+ visibility of which is controlled by code in
+ DirectoryFragment.java. -->
+ <FrameLayout
+ android:id="@+id/thumbnail"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerCrop"
- android:contentDescription="@null" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
+ android:layout_height="wrap_content"
+ android:paddingBottom="8dp">
+
+ <com.android.documentsui.GridItemThumbnail
+ android:id="@+id/icon_thumb"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scaleType="centerCrop"
+ android:contentDescription="@null" />
+
<ImageView
android:id="@+id/icon_mime"
android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
+ android:layout_height="wrap_content"
android:scaleType="centerInside"
android:contentDescription="@null" />
+
+ </FrameLayout>
+
+ <!-- Item nameplate. Has a mime-type icon and some text fields (title,
+ size, mod-time, etc). -->
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/thumbnail"
+ android:layout_toEndOf="@android:id/icon1"
+ android:singleLine="true"
+ android:ellipsize="middle"
+ android:textAlignment="viewStart"
+ android:paddingEnd="12dp"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="@*android:color/primary_text_default_material_light" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@color/item_doc_grid_protect_background"
- android:orientation="vertical"
- android:paddingStart="16dp"
- android:paddingEnd="12dp"
- android:paddingTop="8dp"
- android:paddingBottom="8dp">
+ <TextView
+ android:id="@+id/size"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_toEndOf="@android:id/icon1"
+ android:paddingEnd="4dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAlignment="viewStart"
+ android:textAppearance="@android:style/TextAppearance.Material.Caption"
+ android:textColor="@*android:color/primary_text_default_material_light" />
- <LinearLayout
- android:id="@+id/line1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:baselineAligned="false">
-
- <TextView
- android:id="@android:id/title"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:singleLine="true"
- android:ellipsize="middle"
- android:textAlignment="viewStart"
- android:textAppearance="@android:style/TextAppearance.Material.Subhead"
- android:textColor="@*android:color/primary_text_default_material_dark" />
-
- <ImageView
- android:id="@android:id/icon1"
- android:layout_width="@dimen/root_icon_size"
- android:layout_height="@dimen/root_icon_size"
- android:layout_marginStart="8dp"
- android:scaleType="centerInside"
- android:contentDescription="@null" />
-
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/line2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:baselineAligned="false">
-
- <TextView
- android:id="@+id/date"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="0.5"
- android:singleLine="true"
- android:ellipsize="end"
- android:textAlignment="viewStart"
- android:textAppearance="@android:style/TextAppearance.Material.Caption"
- android:textColor="@*android:color/primary_text_default_material_dark" />
-
- <TextView
- android:id="@+id/size"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="0.5"
- android:layout_marginStart="8dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:textAlignment="viewStart"
- android:textAppearance="@android:style/TextAppearance.Material.Caption"
- android:textColor="@*android:color/primary_text_default_material_dark" />
-
- <ImageView
- android:id="@android:id/icon2"
- android:layout_width="@dimen/root_icon_size"
- android:layout_height="@dimen/root_icon_size"
- android:layout_marginStart="8dp"
- android:scaleType="centerInside"
- android:contentDescription="@null"
- android:visibility="gone" />
-
- </LinearLayout>
-
- </LinearLayout>
-
- </LinearLayout>
-
+ <TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_toEndOf="@id/size"
+ android:paddingEnd="12dp"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAlignment="viewStart"
+ android:textAppearance="@android:style/TextAppearance.Material.Caption"
+ android:textColor="@*android:color/primary_text_default_material_light" />
+
<ImageView
+ android:id="@android:id/icon1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_below="@id/thumbnail"
+ android:layout_alignParentLeft="true"
+ android:layout_alignBottom="@id/size"
+ android:layout_alignTop="@android:id/title"
+ android:scaleType="centerInside"
+ android:contentDescription="@null"
+ android:paddingStart="12dp"
+ android:paddingEnd="8dp"/>
+
+ <!-- Use an explicit spacer so we can align things to it. -->
+ <Space
+ android:id="@+id/bottomPadding"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:src="@drawable/item_doc_grid_overlay"
+ android:layout_height="8dp"
+ android:layout_below="@id/size" />
+
+ <!-- An overlay that draws the item border when it is focused. -->
+ <View
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@id/bottomPadding"
+ android:layout_alignTop="@id/thumbnail"
+ android:layout_alignLeft="@id/thumbnail"
+ android:layout_alignRight="@id/thumbnail"
android:contentDescription="@null"
android:background="@drawable/item_doc_grid_border"
android:duplicateParentState="true" />
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:src="@drawable/item_doc_grid_overlay_icon"
- android:scaleType="center"
- android:contentDescription="@null"
- android:duplicateParentState="true" />
-
-</com.android.documentsui.GridItem>
+</RelativeLayout>
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index a376418..68c8b65 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -24,7 +24,7 @@
<color name="directory_background">@*android:color/material_grey_300</color>
<color name="item_doc_grid_background">@android:color/white</color>
- <color name="item_doc_grid_protect_background">#88000000</color>
+ <color name="item_doc_grid_protect_background">@android:color/white</color>
<color name="band_select_background">#88ffffff</color>
<color name="band_select_border">#44000000</color>
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/GridItem.java b/packages/DocumentsUI/src/com/android/documentsui/GridItemThumbnail.java
similarity index 80%
rename from packages/DocumentsUI/src/com/android/documentsui/GridItem.java
rename to packages/DocumentsUI/src/com/android/documentsui/GridItemThumbnail.java
index 990dca7..38d6d72 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/GridItem.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/GridItemThumbnail.java
@@ -18,22 +18,21 @@
import android.content.Context;
import android.util.AttributeSet;
-import android.widget.FrameLayout;
+import android.widget.ImageView;
/**
- * A FrameLayout subclass used by DirectoryFragment. Ensures that the resulting grid item is always
- * square.
+ * Ensures that grid thumbnails are always square.
*/
-public class GridItem extends FrameLayout {
- public GridItem(Context context) {
+public class GridItemThumbnail extends ImageView {
+ public GridItemThumbnail(Context context) {
super(context);
}
- public GridItem(Context context, AttributeSet attrs) {
+ public GridItemThumbnail(Context context, AttributeSet attrs) {
super(context, attrs);
}
- public GridItem(Context context, AttributeSet attrs, int defStyle) {
+ public GridItemThumbnail(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index b95c001e..21420c8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -1080,14 +1080,12 @@
holder.setSelected(isSelected(position));
- final View line1 = itemView.findViewById(R.id.line1);
final View line2 = itemView.findViewById(R.id.line2);
final ImageView iconMime = (ImageView) itemView.findViewById(R.id.icon_mime);
final ImageView iconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb);
final TextView title = (TextView) itemView.findViewById(android.R.id.title);
final ImageView icon1 = (ImageView) itemView.findViewById(android.R.id.icon1);
- final ImageView icon2 = (ImageView) itemView.findViewById(android.R.id.icon2);
final TextView summary = (TextView) itemView.findViewById(android.R.id.summary);
final TextView date = (TextView) itemView.findViewById(R.id.date);
final TextView size = (TextView) itemView.findViewById(R.id.size);
@@ -1140,13 +1138,14 @@
getDocumentIcon(mContext, docAuthority, docId, docMimeType, docIcon, state));
}
- boolean hasLine1 = false;
boolean hasLine2 = false;
final boolean hideTitle = (state.derivedMode == MODE_GRID) && mHideGridTitles;
if (!hideTitle) {
title.setText(docDisplayName);
- hasLine1 = true;
+ title.setVisibility(View.VISIBLE);
+ } else {
+ title.setVisibility(View.GONE);
}
Drawable iconDrawable = null;
@@ -1154,11 +1153,7 @@
// We've already had to enumerate roots before any results can
// be shown, so this will never block.
final RootInfo root = roots.getRootBlocking(docAuthority, docRootId);
- if (state.derivedMode == MODE_GRID) {
- iconDrawable = root.loadGridIcon(mContext);
- } else {
- iconDrawable = root.loadIcon(mContext);
- }
+ iconDrawable = root.loadIcon(mContext);
if (summary != null) {
final boolean alwaysShowSummary = getResources()
@@ -1200,16 +1195,10 @@
}
if (icon1 != null) icon1.setVisibility(View.GONE);
- if (icon2 != null) icon2.setVisibility(View.GONE);
if (iconDrawable != null) {
- if (hasLine1) {
- icon1.setVisibility(View.VISIBLE);
- icon1.setImageDrawable(iconDrawable);
- } else {
- icon2.setVisibility(View.VISIBLE);
- icon2.setImageDrawable(iconDrawable);
- }
+ icon1.setVisibility(View.VISIBLE);
+ icon1.setImageDrawable(iconDrawable);
}
if (docLastModified == -1) {
@@ -1231,9 +1220,6 @@
size.setVisibility(View.GONE);
}
- if (line1 != null) {
- line1.setVisibility(hasLine1 ? View.VISIBLE : View.GONE);
- }
if (line2 != null) {
line2.setVisibility(hasLine2 ? View.VISIBLE : View.GONE);
}
@@ -1243,7 +1229,6 @@
iconMime.setAlpha(iconAlpha);
iconThumb.setAlpha(iconAlpha);
if (icon1 != null) icon1.setAlpha(iconAlpha);
- if (icon2 != null) icon2.setAlpha(iconAlpha);
if (DEBUG_ENABLE_DND) {
setupDragAndDropOnDocumentView(itemView, cursor);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 501392c..723700d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -249,15 +249,6 @@
}
}
- public Drawable loadGridIcon(Context context) {
- if (derivedIcon != 0) {
- return IconUtils.applyTintAttr(context, derivedIcon,
- android.R.attr.textColorPrimaryInverse);
- } else {
- return IconUtils.loadPackageIcon(context, authority, icon);
- }
- }
-
public Drawable loadToolbarIcon(Context context) {
if (derivedIcon != 0) {
return IconUtils.applyTintAttr(context, derivedIcon,
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index 5b1e45d..c7b217c 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -92,8 +92,8 @@
<string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="6853071165802933545">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地尝试解锁手机。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统将移除此工作资料,这会删除所有的工作资料数据。"</string>
<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4686386497449912146">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁平板电脑。系统将移除此工作资料,这会删除所有的工作资料数据。"</string>
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4951507352869831265">"您已经 <xliff:g id="NUMBER">%d</xliff:g> 次错误地尝试解锁手机。系统将移除此工作资料,这会删除所有的工作资料数据。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已连续 <xliff:g id="NUMBER_0">%d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已连续 <xliff:g id="NUMBER_0">%d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已连续 <xliff:g id="NUMBER_0">%d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已连续 <xliff:g id="NUMBER_0">%d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM卡PIN码不正确,您现在必须联系运营商为您解锁设备。"</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
<item quantity="other">SIM 卡 PIN 码不正确,您还可尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item>
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 6b8aa47..a2f710d 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -69,7 +69,9 @@
android:layout_height="wrap_content"
android:layout_marginStart="16dip"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary">
+ android:textColor="?android:attr/textColorPrimary"
+ android:singleLine="true"
+ android:ellipsize="end">
</TextView>
<TextView
@@ -87,7 +89,9 @@
android:layout_height="wrap_content"
android:layout_marginStart="16dip"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorPrimary">
+ android:textColor="?android:attr/textColorPrimary"
+ android:singleLine="true"
+ android:ellipsize="end">
</TextView>
</LinearLayout>
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index 0cfa0de..1c39a7d 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Geen verbinding met drukker nie"</string>
<string name="reason_unknown" msgid="5507940196503246139">"onbekend"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – nie beskikbaar nie"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Gebruik <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Jou dokument kan dalk deur een of meer bedieners op pad na die drukker gaan."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Swart en wit"</item>
<item msgid="2762241247228983754">"Kleur"</item>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index 72fc67b..4d8b85e 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"ከአታሚ ጋር ምንም ግንኙነት የለም"</string>
<string name="reason_unknown" msgid="5507940196503246139">"አይታወቅም"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – አይገኝም"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> ይጠቀሙ?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ሰነድዎ ወደ አታሚው በሚሄድበት ወቅት በአንድ ወይም ከዚያ በላይ አገልጋዮች ውስጥ ሊያልፍ ይችላል።"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"ጥቁር እና ነጭ"</item>
<item msgid="2762241247228983754">"ቀለም"</item>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index e28c7bd..0fa6ec2 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -82,6 +82,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"لا يوجد اتصال بالطابعة"</string>
<string name="reason_unknown" msgid="5507940196503246139">"غير معروف"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – غير متاحة"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"هل تريد استخدام <xliff:g id="SERVICE">%1$s</xliff:g>؟"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"من الممكن أن يمر المستند عبر خادم أو أكثر أثناء إرساله إلى الطابعة."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"أبيض وأسود"</item>
<item msgid="2762241247228983754">"ملونة"</item>
diff --git a/packages/PrintSpooler/res/values-az-rAZ/strings.xml b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
index c102745..1837db4 100644
--- a/packages/PrintSpooler/res/values-az-rAZ/strings.xml
+++ b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printerə heç bir bağlantı yoxdur"</string>
<string name="reason_unknown" msgid="5507940196503246139">"naməlum"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>– əlçatmaz"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> xidmətindən istifadə edilsin?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Sənədiniz printerə qədər bir və ya daha çox server vasitəsilə keçə bilər."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Qara & Ağ"</item>
<item msgid="2762241247228983754">"Rəng"</item>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index c88d0d4..9a8ccef 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Няма връзка с принтера"</string>
<string name="reason_unknown" msgid="5507940196503246139">"няма данни"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – не е налице"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Да се използва ли „<xliff:g id="SERVICE">%1$s</xliff:g>“?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"По пътя към принтера документът ви може да премине през един или повече сървъри."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Черно-бяло"</item>
<item msgid="2762241247228983754">"Цветно"</item>
diff --git a/packages/PrintSpooler/res/values-bn-rBD/strings.xml b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
index 45f20a0..4f1646d 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"মুদ্রকে কোনো সংযোগ নেই"</string>
<string name="reason_unknown" msgid="5507940196503246139">"অজানা"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – অনুপলব্ধ"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> ব্যবহার করবেন?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"আপনার দস্তাবেজ মুদ্রকে যাওয়ার সময় এক বা একাধিক সার্ভারের মাধ্যমে পাস হতে পারে।"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"কালো এবং সাদা"</item>
<item msgid="2762241247228983754">"রঙ"</item>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index 612be97..fa34c52 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hi ha connexió amb la impressora"</string>
<string name="reason_unknown" msgid="5507940196503246139">"desconegut"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>: no disponible"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Vols fer servir <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"És possible que el document passi com a mínim per un servidor abans d\'imprimir-se."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Blanc i negre"</item>
<item msgid="2762241247228983754">"Color"</item>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 99ed75d..5c98d616 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -78,6 +78,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nelze se připojit k tiskárně"</string>
<string name="reason_unknown" msgid="5507940196503246139">"neznámé"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – není k dispozici"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Použít službu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dokument může cestou do tiskárny projít jedním i více servery."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Černobíle"</item>
<item msgid="2762241247228983754">"Barevně"</item>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 526e976..e57d435 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen forbindelse til printer"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ukendt"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ikke tilgængelig"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Vil du bruge <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dit dokument passerer muligvis gennem én eller flere servere på vej til printeren."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Sort/hvid"</item>
<item msgid="2762241247228983754">"Farve"</item>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index ef5e34c..1005b45 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Keine Verbindung zum Drucker"</string>
<string name="reason_unknown" msgid="5507940196503246139">"unbekannt"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – nicht verfügbar"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> verwenden?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Ihr Dokument passiert bei der Übermittlung an den Drucker möglicherweise einen oder mehrere Server."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Schwarz-weiß"</item>
<item msgid="2762241247228983754">"Farbe"</item>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index a4bb04c..75b8447 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Δεν υπάρχει σύνδεση με εκτυπωτή"</string>
<string name="reason_unknown" msgid="5507940196503246139">"άγνωστο"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – μη διαθέσιμο"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Να χρησιμοποιηθεί η υπηρεσία <xliff:g id="SERVICE">%1$s</xliff:g>;"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Το έγγραφό σας μπορεί να περάσει από έναν ή περισσότερους διακομιστές κατά τη μετάβαση στον εκτυπωτή."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Ασπρόμαυρο"</item>
<item msgid="2762241247228983754">"Χρώμα"</item>
diff --git a/packages/PrintSpooler/res/values-en-rAU/strings.xml b/packages/PrintSpooler/res/values-en-rAU/strings.xml
index 9f0d7e5..87349c2 100644
--- a/packages/PrintSpooler/res/values-en-rAU/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rAU/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"No connection to printer"</string>
<string name="reason_unknown" msgid="5507940196503246139">"unknown"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – unavailable"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Use <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Your document may pass through one or more servers on its way to the printer."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Black & White"</item>
<item msgid="2762241247228983754">"Colour"</item>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index 9f0d7e5..87349c2 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"No connection to printer"</string>
<string name="reason_unknown" msgid="5507940196503246139">"unknown"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – unavailable"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Use <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Your document may pass through one or more servers on its way to the printer."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Black & White"</item>
<item msgid="2762241247228983754">"Colour"</item>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index 9f0d7e5..87349c2 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"No connection to printer"</string>
<string name="reason_unknown" msgid="5507940196503246139">"unknown"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – unavailable"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Use <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Your document may pass through one or more servers on its way to the printer."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Black & White"</item>
<item msgid="2762241247228983754">"Colour"</item>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index ef0dbb1..ffd4d79 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hay conexión con la impresora."</string>
<string name="reason_unknown" msgid="5507940196503246139">"desconocido"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>: no disponible"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"¿Deseas usar <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Es posible que el documento pase por uno o varios servidores antes de imprimirse."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Blanco y negro"</item>
<item msgid="2762241247228983754">"Color"</item>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index 067c134..5660d1b 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hay conexión con la impresora"</string>
<string name="reason_unknown" msgid="5507940196503246139">"desconocido"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – no disponible"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"¿Usar <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Es posible que el documento pase por uno o varios servidores antes de imprimirse."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Blanco y negro"</item>
<item msgid="2762241247228983754">"Color"</item>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index 0227131..fb0f320 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printeriühendus puudub"</string>
<string name="reason_unknown" msgid="5507940196503246139">"teadmata"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – pole saadaval"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Kas soovite kasutada teenust <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Printerini jõudmiseks võib dokument läbida ühe või mitu serverit."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Mustvalge"</item>
<item msgid="2762241247228983754">"Värv"</item>
diff --git a/packages/PrintSpooler/res/values-eu-rES/strings.xml b/packages/PrintSpooler/res/values-eu-rES/strings.xml
index 461a92f..8402a9c 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Inprimagailua ez dago konektatuta"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ezezaguna"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>: ez dago erabilgarri"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> erabili nahi duzu?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Baliteke dokumentuak zerbitzari bat edo gehiagotan zehar igarotzea inprimagailurako bidean."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Zuri-beltza"</item>
<item msgid="2762241247228983754">"Koloretakoa"</item>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 0e1629f..ba78460 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"اتصال با چاپگر برقرار نیست"</string>
<string name="reason_unknown" msgid="5507940196503246139">"نامعلوم"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - در دسترس نیست"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"از <xliff:g id="SERVICE">%1$s</xliff:g> استفاده شود؟"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ممکن است سندتان برای رسیدن به چاپگر از یک یا چند سرور عبور کند."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"سیاه و سفید"</item>
<item msgid="2762241247228983754">"رنگی"</item>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index faf40e2..3a82702 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ei yhteyttä tulostimeen"</string>
<string name="reason_unknown" msgid="5507940196503246139">"tuntematon"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ei käytettävissä"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Käytetäänkö palvelua <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Asiakirja saattaa kulkea yhden tai useamman palvelimen kautta matkalla tulostimeen."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Mustavalkoinen"</item>
<item msgid="2762241247228983754">"Väri"</item>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index f949bb7..f49885a 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Aucune connexion à l\'imprimante"</string>
<string name="reason_unknown" msgid="5507940196503246139">"inconnu"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> — indisponible"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Utiliser <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Votre document peut passer par un ou plusieurs serveurs avant d\'arriver à l\'imprimante."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Noir et blanc"</item>
<item msgid="2762241247228983754">"Couleur"</item>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 1f5c716..4dcfa65 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Aucune connexion à l\'imprimante."</string>
<string name="reason_unknown" msgid="5507940196503246139">"inconnue"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – indisponible"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Utiliser <xliff:g id="SERVICE">%1$s</xliff:g> ?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Votre document peut passer par un ou plusieurs serveurs avant d\'être envoyé sur l\'imprimante."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Noir et blanc"</item>
<item msgid="2762241247228983754">"Couleur"</item>
diff --git a/packages/PrintSpooler/res/values-gl-rES/strings.xml b/packages/PrintSpooler/res/values-gl-rES/strings.xml
index 0d4b040..c805e30 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Non hai conexión coa impresora"</string>
<string name="reason_unknown" msgid="5507940196503246139">"descoñecido"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>: non dispoñible"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Queres usar <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"É posible que o teu documento pase por un ou máis servidores antes de imprimirse."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Branco e negro"</item>
<item msgid="2762241247228983754">"Cor"</item>
diff --git a/packages/PrintSpooler/res/values-gu-rIN/strings.xml b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
index 28ffc2a..51820f2 100644
--- a/packages/PrintSpooler/res/values-gu-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"પ્રિન્ટર માટે કોઈ કનેક્શન નથી"</string>
<string name="reason_unknown" msgid="5507940196503246139">"અજાણ્યું"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – અનુપલબ્ધ"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> નો ઉપયોગ કરીએ?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"તમારો દસ્તાવેજ પ્રિન્ટર સુધીના તેના માર્ગમાં એક અથવા વધુ સર્વર્સથી પસાર થઈ શકે છે."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"શ્યામ અને શ્વેત"</item>
<item msgid="2762241247228983754">"રંગ"</item>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 1a0f7d1..e2bc012 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिंटर के लिए कोई कनेक्शन नहीं"</string>
<string name="reason_unknown" msgid="5507940196503246139">"अज्ञात"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – अनुपलब्ध"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> का उपयोग करें?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"प्रिंटर पर जाते समय आपका दस्तावेज़ एक या अधिक सर्वर से गुज़र सकता है."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"श्याम और श्वेत"</item>
<item msgid="2762241247228983754">"रंग"</item>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 3e38d65..64c4a58 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -76,6 +76,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nema veze s pisačem"</string>
<string name="reason_unknown" msgid="5507940196503246139">"nepoznato"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – zadatak nije dostupan"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Želite li upotrijebiti uslugu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Na putu do pisača vaš dokument može proći kroz jedan ili više poslužitelja."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Crno-bijelo"</item>
<item msgid="2762241247228983754">"U boji"</item>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 2b24b1f..58e7852 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nincs kapcsolat a nyomtatóval"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ismeretlen"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – nem érhető el"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Használni szeretné a következő szolgáltatást: <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"A dokumentum áthaladhat egy vagy több szerveren, mielőtt a nyomtatóhoz érne."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Fekete-fehér"</item>
<item msgid="2762241247228983754">"Szín"</item>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index 56f94b4..88e9192 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Տպիչի հետ կապ չկա"</string>
<string name="reason_unknown" msgid="5507940196503246139">"անհայտ"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> տպիչն անհասանելի է"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Օգտագործե՞լ <xliff:g id="SERVICE">%1$s</xliff:g>-ը:"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Հնարավոր է՝ փաստաթուղթը մի քանի սերվերներով անցնի մինչ տպվելը:"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Սև ու սպիտակ"</item>
<item msgid="2762241247228983754">"Գույնը"</item>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index d09fcfe..de76536 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Tidak ada sambungan ke printer"</string>
<string name="reason_unknown" msgid="5507940196503246139">"tak diketahui"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – tidak tersedia"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Gunakan <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dokumen Anda dapat melewati satu atau beberapa server saat menuju printer."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Hitam & Putih"</item>
<item msgid="2762241247228983754">"Warna"</item>
diff --git a/packages/PrintSpooler/res/values-is-rIS/strings.xml b/packages/PrintSpooler/res/values-is-rIS/strings.xml
index bf13ebf..3f8aa65 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Engin tenging við prentara"</string>
<string name="reason_unknown" msgid="5507940196503246139">"óþekkt"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ekki í boði"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Nota <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Skjalið gæti þurft að fara í gegnum einn eða fleiri þjóna á leið sinni til prentarans."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Svarthvítt"</item>
<item msgid="2762241247228983754">"Í lit"</item>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index b052341..394dc88 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nessun collegamento alla stampante"</string>
<string name="reason_unknown" msgid="5507940196503246139">"sconosciuto"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - non disponibile"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Utilizzare <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Il tuo documento potrebbe passare da uno o più server per raggiungere la stampante."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Bianco e nero"</item>
<item msgid="2762241247228983754">"A colori"</item>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index bb1967d..5c5e5d9 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -78,6 +78,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"אין חיבור למדפסת"</string>
<string name="reason_unknown" msgid="5507940196503246139">"לא ידוע"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – לא זמינה"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"האם להשתמש ב-<xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ייתכן שהמסמך שלך יעבור בשרת אחד או יותר בדרכו למדפסת."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"שחור ולבן"</item>
<item msgid="2762241247228983754">"צבע"</item>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index 8ef7517..6a396b3 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"プリンタに接続されていません"</string>
<string name="reason_unknown" msgid="5507940196503246139">"不明"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>–使用不可"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g>を利用しますか?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ドキュメントは1つ以上のサーバーを経由してプリンタに送信されることがあります。"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"モノクロ"</item>
<item msgid="2762241247228983754">"カラー"</item>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index b65d013..44e77d7 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"პრინტერთან კავშირი არ არის"</string>
<string name="reason_unknown" msgid="5507940196503246139">"უცნობი"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – მიუწვდომელია"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"გსურთ, გამოიყენოთ <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"პრინტერამდე გზად დოკუმენტმა შეიძლება ერთი ან მეტი სერვერი გაიაროს."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"შავ-თეთრი"</item>
<item msgid="2762241247228983754">"ფერი"</item>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index ef914f0c..a79a511 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтермен байланыс жоқ"</string>
<string name="reason_unknown" msgid="5507940196503246139">"белгісіз"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – қол жетімсіз"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> қолданылсын ба?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Құжат принтерге жеткенше бір немесе бірнеше серверден өтуі мүмкін."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Қара & Ақ"</item>
<item msgid="2762241247228983754">"Түс"</item>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index 3aac97f..87f4fde 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មានការភ្ជាប់ទៅម៉ាស៊ីនបោះពុម្ព"</string>
<string name="reason_unknown" msgid="5507940196503246139">"មិនស្គាល់"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – មិនអាចប្រើបាន"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"ប្រើ <xliff:g id="SERVICE">%1$s</xliff:g> ឬ?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ឯកសាររបស់អ្នកអាចនឹងឆ្លងកាត់ម៉ាស៊ីនមេមួយ ឬច្រើននៅពេលដែលវាធ្វើដំណើរទៅកាន់ម៉ាស៊ីនបោះពុម្ព។"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"ស & ខ្មៅ"</item>
<item msgid="2762241247228983754">"ពណ៌"</item>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index 72e0bac..eff1127 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"ಮುದ್ರಕಕ್ಕೆ ಸಂಪರ್ಕವಿಲ್ಲ"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ಅಜ್ಞಾತ"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ಲಭ್ಯವಿಲ್ಲ"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> ಬಳಸುವುದೇ?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ನಿಮ್ಮ ಡಾಕ್ಯುಮೆಂಟ್ ಪ್ರಿಂಟರ್ಗೆ ಹೋಗುವ ಸಂದರ್ಭದಲ್ಲಿ ಒಂದು ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೆಚ್ಚು ಸರ್ವರ್ಗಳ ಮೂಲಕ ಹಾದು ಹೋಗಬಹುದು."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"ಕಪ್ಪು & ಬಿಳುಪು"</item>
<item msgid="2762241247228983754">"ಬಣ್ಣ"</item>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index 0d9a4dd..7613ad7 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"프린터와 연결되지 않음"</string>
<string name="reason_unknown" msgid="5507940196503246139">"알 수 없음"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – 사용할 수 없음"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g>을(를) 사용할까요?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"문서가 프린터로 전송되는 중에 하나 이상의 서버를 통과할 수 있습니다."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"흑백"</item>
<item msgid="2762241247228983754">"컬러"</item>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index 7f6eb10..2ea1b57 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтер менен байланыш жок"</string>
<string name="reason_unknown" msgid="5507940196503246139">"белгисиз"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – жеткиликтүү эмес"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> колдонулсунбу?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Принтерге жеткиче документиңиз бир же андан көп серверлерден өтүшү мүмкүн."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Кара-ак"</item>
<item msgid="2762241247228983754">"Түстүү"</item>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index 7e65b72..511a72f 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"ບໍ່ມີການເຊື່ອມຕໍ່ຫາເຄື່ອງພິມ"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ບໍ່ຮູ້ຈັກ"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - ບໍ່ມີຢູ່"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"ໃຊ້ <xliff:g id="SERVICE">%1$s</xliff:g> ບໍ?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ເອກະສານຂອງທ່ານອາດເດີນທາງຜ່ານໜຶ່ງ ຫຼື ຫຼາຍເຊີບເວີ ເພື່ອໄປຮອດເຄື່ອງພິມ."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"ຂາວດຳ"</item>
<item msgid="2762241247228983754">"ສີ"</item>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index a3129cc..ce912be 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -78,6 +78,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nėra ryšio su spausdintuvu"</string>
<string name="reason_unknown" msgid="5507940196503246139">"nežinoma"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"„<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“ – nepasiekiama"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Naudoti „<xliff:g id="SERVICE">%1$s</xliff:g>“?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Kai dokumentas siunčiamas į spausdintuvą, jis gali būti perduodamas per vieną ar daugiau serverių."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Nespalvotas"</item>
<item msgid="2762241247228983754">"Spalva"</item>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index daadf99..bfba6c8 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -76,6 +76,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nav savienojuma ar printeri"</string>
<string name="reason_unknown" msgid="5507940196503246139">"nezināms"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> — nav pieejams"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Vai izmantot pakalpojumu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dokuments, iespējams, tiek pārsūtīts caur vienu vai vairākiem serveriem, līdz tas nonāk līdz printerim."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Melnbalts"</item>
<item msgid="2762241247228983754">"Krāsa"</item>
diff --git a/packages/PrintSpooler/res/values-mk-rMK/strings.xml b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
index 3ebc1c9..a81db01 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нема поврзување со печатач"</string>
<string name="reason_unknown" msgid="5507940196503246139">"непознато"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - недостапен"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Користи <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"На пат до печатачот, документот може да помине преку еден или повеќе сервери."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Црно-бела"</item>
<item msgid="2762241247228983754">"Во боја"</item>
diff --git a/packages/PrintSpooler/res/values-ml-rIN/strings.xml b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
index 63b4060..c14c5ad 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"പ്രിന്ററിൽ കണക്ഷനൊന്നുമില്ല"</string>
<string name="reason_unknown" msgid="5507940196503246139">"അജ്ഞാതം"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ലഭ്യമല്ല"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> ഉപയോഗിക്കണോ?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"നിങ്ങളുടെ പ്രമാണം പ്രിന്ററിലേക്ക് പോകുന്നതിനിടെ അത് ഒന്നോ അതിലധികമോ സെർവറുകളിലൂടെ കടന്നുപോകാനിടയുണ്ട്."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"കറുപ്പ് & വെള്ള"</item>
<item msgid="2762241247228983754">"നിറം"</item>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index a8628c9..789f085 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтер холбогдоогүй байна"</string>
<string name="reason_unknown" msgid="5507940196503246139">"тодорхойгүй"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ашиглах боломжгүй"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g>-г ашиглах уу?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Таны документ хэвлэгчид иртэл нэг эсвэл хэд хэдэн серверээр дамжина."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Хар & Цагаан"</item>
<item msgid="2762241247228983754">"Өнгө"</item>
diff --git a/packages/PrintSpooler/res/values-mr-rIN/strings.xml b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
index c08e440..1d859cf 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिंटरवर कोणतेही कनेक्शन नाही"</string>
<string name="reason_unknown" msgid="5507940196503246139">"अज्ञात"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – अनुपलब्ध"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> वापरायची?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"आपला दस्तऐवज प्रिंटरपर्यंत पोहचण्यापूर्वी एक किंवा अधिक सर्व्हरद्वारे जाऊ शकतो."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"कृष्ण धवल"</item>
<item msgid="2762241247228983754">"रंग"</item>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index 4ed1019..c86d0bf 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Tiada sambungan ke pencetak"</string>
<string name="reason_unknown" msgid="5507940196503246139">"tidak diketahui"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – tidak tersedia"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Gunakan <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dokumen anda mungkin melalui satu atau beberapa pelayan dalam perjalanan ke pencetak."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Hitam & Putih"</item>
<item msgid="2762241247228983754">"Warna"</item>
diff --git a/packages/PrintSpooler/res/values-my-rMM/strings.xml b/packages/PrintSpooler/res/values-my-rMM/strings.xml
index 0a65a11..9b2760a 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"စာထုတ်စက်နဲ့ ဆက်သွယ်ထားမှု မရှိပါ"</string>
<string name="reason_unknown" msgid="5507940196503246139">"အကြောင်းအရာ မသိရှိ"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – မတွေ့ရှိပါ"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g>ကိုသုံးမလား။"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"သင်၏ စာရွက်စာတမ်းများသည် ပရင်တာထံသို့ သွားစဉ် ဆာဗာ တစ်ခု သို့မဟုတ် ပိုများပြီး ဖြတ်ကျော်နိုင်ရသည်။"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"အဖြူ အမည်း"</item>
<item msgid="2762241247228983754">"ရောင်စုံ"</item>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index 7c74b39..cdec56f 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen forbindelse med skriveren"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ukjent"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – utilgjengelig"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Vil du bruke <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dokumentet ditt kan gå via flere tjenere før det når skriveren."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Svart og hvitt"</item>
<item msgid="2762241247228983754">"Farge"</item>
diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
index 42cd98b..427a9ae 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिन्टरमा कुनै जडान छैन"</string>
<string name="reason_unknown" msgid="5507940196503246139">"अज्ञात"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - अनुपलब्ध"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> प्रयोग गर्ने हो?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"तपाईँको कागजात प्रिन्टरमा जाँदा यसको मार्गमा एक वा धेरै सर्भरहरू पार हुनसक्छन्।"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"कालो & सेतो"</item>
<item msgid="2762241247228983754">"रङ्ग"</item>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 4855e31..12d52f9 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Geen verbinding met printer"</string>
<string name="reason_unknown" msgid="5507940196503246139">"onbekend"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – niet beschikbaar"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> gebruiken?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Je document kan via een of meer servers naar de printer worden verzonden."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Zwart-wit"</item>
<item msgid="2762241247228983754">"Kleur"</item>
diff --git a/packages/PrintSpooler/res/values-pa-rIN/strings.xml b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
index 912cf4a..b8d0602 100644
--- a/packages/PrintSpooler/res/values-pa-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"ਪ੍ਰਿੰਟਰ ਲਈ ਕੋਈ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ਅਗਿਆਤ"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ਅਣਉਪਲਬਧ"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"ਕੀ <xliff:g id="SERVICE">%1$s</xliff:g> ਵਰਤਣੀ ਹੈ?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ਤੁਹਾਡਾ ਦਸਤਾਵੇਜ਼ ਪ੍ਰਿੰਟਰ ਵਿੱਚ ਜਾਣ ਲਈ ਇੱਕ ਜਾਂ ਦੋ ਸਰਵਰਾਂ ਵਿੱਚੋਂ ਲੰਘਦਾ ਹੈ।"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"ਕਾਲਾ & ਚਿੱਟਾ"</item>
<item msgid="2762241247228983754">"ਰੰਗ"</item>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 055fb5f..dac4b0822 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -78,6 +78,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Brak połączenia z drukarką"</string>
<string name="reason_unknown" msgid="5507940196503246139">"brak informacji"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – niedostępne"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Użyć usługi <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Zanim dokument dotrze do drukarki, może przejść przez jeden lub kilka serwerów."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Czarno-białe"</item>
<item msgid="2762241247228983754">"Kolor"</item>
diff --git a/packages/PrintSpooler/res/values-pt-rBR/strings.xml b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
index 9e38506..b073ce1 100644
--- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Sem conexão com a impressora"</string>
<string name="reason_unknown" msgid="5507940196503246139">"desconhecido"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – não disponível"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Usar <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Seu documento pode passar por um ou mais servidores até chegar à impressora."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Preto e branco"</item>
<item msgid="2762241247228983754">"Cor"</item>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 73fabab..da512b1 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Sem ligação à impressora"</string>
<string name="reason_unknown" msgid="5507940196503246139">"desconhecido"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – indisponível"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Pretende utilizar o <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"O seu documento pode passar por um ou mais servidores no respetivo caminho para a impressora."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Preto e branco"</item>
<item msgid="2762241247228983754">"Cor"</item>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 9e38506..b073ce1 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Sem conexão com a impressora"</string>
<string name="reason_unknown" msgid="5507940196503246139">"desconhecido"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – não disponível"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Usar <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Seu documento pode passar por um ou mais servidores até chegar à impressora."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Preto e branco"</item>
<item msgid="2762241247228983754">"Cor"</item>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index 3ff1045..1a44182 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -76,6 +76,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nu există conexiune la o imprimantă"</string>
<string name="reason_unknown" msgid="5507940196503246139">"necunoscut"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - indisponibil"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Folosiți <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Documentul poate trece prin unul sau mai multe servere pe calea spre imprimantă."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Alb-negru"</item>
<item msgid="2762241247228983754">"Color"</item>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index a4e12fe..a6ef092 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -78,6 +78,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нет связи с принтером"</string>
<string name="reason_unknown" msgid="5507940196503246139">"неизвестно"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – недоступен"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Использовать <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Документ может пересылаться на принтер через несколько серверов."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Черно-белая"</item>
<item msgid="2762241247228983754">"Цветная"</item>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index e8052d6..7520459 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"මුද්රණ යන්ත්රය වෙත සම්බන්ධය නැත"</string>
<string name="reason_unknown" msgid="5507940196503246139">"නොදනී"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ලද නොහැක"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> භාවිත කරන්නද?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"ඔබගේ ලේඛනය මුද්රණ යන්ත්රයට යන අතරතුර සේවාදායක එකක් හෝ කිහිපයක් හරහා යා හැක."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"කළු සහ සුදු"</item>
<item msgid="2762241247228983754">"වර්ණය"</item>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 3e82076..4575040 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -78,6 +78,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Žiadne pripojenie k tlačiarni"</string>
<string name="reason_unknown" msgid="5507940196503246139">"neznáme"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – nie je k dispozícii"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Použiť službu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Skôr ako sa váš dokument dostane do tlačiarne, môže prejsť jedným alebo viacerými servermi."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Čiernobiele"</item>
<item msgid="2762241247228983754">"Farba"</item>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index 75c2abe..c0dfdb4 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -78,6 +78,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ni povezave s tiskalnikom"</string>
<string name="reason_unknown" msgid="5507940196503246139">"neznano"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ni na voljo"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Želite uporabiti storitev <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dokument gre lahko na poti do tiskalnika skozi enega ali več strežnikov."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Črno-belo"</item>
<item msgid="2762241247228983754">"Barvno"</item>
diff --git a/packages/PrintSpooler/res/values-sq-rAL/strings.xml b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
index adbf700..dbbf238 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printeri nuk është i lidhur"</string>
<string name="reason_unknown" msgid="5507940196503246139">"e panjohur"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – nuk mundësohet"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Përdor <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dokumenti mund të kalojë përmes një ose shumë serverëve deri te printeri."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Bardhezi"</item>
<item msgid="2762241247228983754">"Ngjyra"</item>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index 58e9622..5589298 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -76,6 +76,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нема везе са штампачем"</string>
<string name="reason_unknown" msgid="5507940196503246139">"непознато"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – недоступан"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Желите ли да користите <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Документ може да прође кроз један или више сервера на путу до штампача."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Црно-бело"</item>
<item msgid="2762241247228983754">"Боја"</item>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index 0434903..a97430e 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen anslutning till skrivaren"</string>
<string name="reason_unknown" msgid="5507940196503246139">"okänt"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – inte tillgänglig"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Vill du använda <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"På vägen till skrivaren kan dokumentet passera en eller flera servrar."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Svartvit"</item>
<item msgid="2762241247228983754">"Färg"</item>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 7c08316..f4d51bf 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Hakuna muunganisho kwa printa"</string>
<string name="reason_unknown" msgid="5507940196503246139">"haijulikani"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - haipatikani"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Ungependa kutumia <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Huenda hati yako ikapitia seva moja au zaidi kabla ya kufika kwenye printa."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Nyeusi na Nyeupe"</item>
<item msgid="2762241247228983754">"Rangi"</item>
diff --git a/packages/PrintSpooler/res/values-ta-rIN/strings.xml b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
index 4c9f135..4e292d2 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"அச்சுப்பொறியுடன் இணைக்கப்படவில்லை"</string>
<string name="reason_unknown" msgid="5507940196503246139">"அறியப்படாதது"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – இல்லை"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g>ஐப் பயன்படுத்தவா?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"உங்கள் ஆவணம் பிரிண்டருக்குச் செல்லும் வழியில் ஒன்று அல்லது அதற்கு மேற்பட்ட சேவையகங்களைக் கடந்து செல்லக்கூடும்."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"கருப்பு & வெள்ளை"</item>
<item msgid="2762241247228983754">"வண்ணம்"</item>
diff --git a/packages/PrintSpooler/res/values-te-rIN/strings.xml b/packages/PrintSpooler/res/values-te-rIN/strings.xml
index ffa994b..8cb5aa6 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"ప్రింటర్కు కనెక్షన్ లేదు"</string>
<string name="reason_unknown" msgid="5507940196503246139">"తెలియదు"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – అందుబాటులో లేదు"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g>ని ఉపయోగించాలా?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"మీ పత్రం ప్రింటర్కు వెళ్లే మార్గంలో ఒకటి లేదా అంతకంటే ఎక్కువ సర్వర్ల గుండా వెళ్లవచ్చు."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"నలుపు & తెలుపు"</item>
<item msgid="2762241247228983754">"రంగు"</item>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index 89e3082..c501cf9 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"ไม่มีการเชื่อมต่อไปยังเครื่องพิมพ์"</string>
<string name="reason_unknown" msgid="5507940196503246139">"ไม่ทราบ"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ไม่พร้อมใช้งาน"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"ใช้ <xliff:g id="SERVICE">%1$s</xliff:g> ไหม"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"เอกสารของคุณอาจต้องผ่านมากกว่าหนึ่งเซิร์ฟเวอร์ระหว่างส่งไปยังเครื่องพิมพ์"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"ขาวดำ"</item>
<item msgid="2762241247228983754">"สี"</item>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index 445d8b0..18942e2 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Hindi nakakonekta sa printer"</string>
<string name="reason_unknown" msgid="5507940196503246139">"hindi alam"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – hindi available"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Gusto mo bang gamitin ang <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Bago ma-print ang iyong dokumento, maaari itong dumaan sa isa o higit pang mga server."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Black & White"</item>
<item msgid="2762241247228983754">"Kulay"</item>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index 66d1e99..a7ef18c 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Yazıcı bağlantısı yok"</string>
<string name="reason_unknown" msgid="5507940196503246139">"bilinmiyor"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – kullanılamıyor"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> kullanılsın mı?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Dokümanınız yazıcıya giderken bir veya daha fazla sunucudan geçebilir."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Siyah Beyaz"</item>
<item msgid="2762241247228983754">"Renkli"</item>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index fcd3fa6..1e21c06 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -78,6 +78,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Немає з’єднання з принтером"</string>
<string name="reason_unknown" msgid="5507940196503246139">"невідомо"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"Завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" не доступне"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Увімкнути службу <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Коли ви надсилаєте документ на принтер, він може проходити через декілька серверів."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Чорно-білий"</item>
<item msgid="2762241247228983754">"Колір"</item>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 2c2c460..7356cdb 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"پرنٹر کے ساتھ کوئی کنکشن نہیں ہے"</string>
<string name="reason_unknown" msgid="5507940196503246139">"نامعلوم"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – دستیاب نہیں ہے"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> استعمال کریں؟"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"آپ کی دستاویز پرنٹر تک جاتے ہوئے ممکن ہے ایک یا زیادہ سرورز سے گزرے۔"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"سیاہ و سفید"</item>
<item msgid="2762241247228983754">"رنگ"</item>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index f88eca5..4b11608 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printer ulanmagan"</string>
<string name="reason_unknown" msgid="5507940196503246139">"noma’lum"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – mavjud emas"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> xizmatidan foydalanilsinmi?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Hujjatingiz chop etilishidan oldin bir yoki bir necha serverlardan o‘tishi mumkin."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Oq & qora"</item>
<item msgid="2762241247228983754">"Rang"</item>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index 2d1e8fa..af237a4 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Không có kết nối nào với máy in"</string>
<string name="reason_unknown" msgid="5507940196503246139">"không xác định"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – không khả dụng"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Sử dụng <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Tài liệu của bạn có thể đi qua một hoặc nhiều máy chủ trên đường đến máy in."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Đen trắng"</item>
<item msgid="2762241247228983754">"Màu"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index 553bc89..9e8e166 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"未与打印机建立连接"</string>
<string name="reason_unknown" msgid="5507940196503246139">"未知"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - 无法使用"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"要使用<xliff:g id="SERVICE">%1$s</xliff:g>吗?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"您的文档可能会通过一个或多个服务器发送至打印机。"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"黑白"</item>
<item msgid="2762241247228983754">"彩色"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 74b301f..41a9f8e 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"尚未與打印機連線"</string>
<string name="reason_unknown" msgid="5507940196503246139">"不明"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – 無法使用"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"要使用 <xliff:g id="SERVICE">%1$s</xliff:g> 嗎?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"您的文件可能會通過一部或多部伺服器才傳送至打印機。"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"黑白"</item>
<item msgid="2762241247228983754">"彩色"</item>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index d91fe52..5e391fa 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"尚未與印表機建立連線"</string>
<string name="reason_unknown" msgid="5507940196503246139">"不明"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – 無法使用"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"要使用「<xliff:g id="SERVICE">%1$s</xliff:g>」嗎?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"您的文件可能會透過一或多個伺服器輾轉傳送至印表機。"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"黑白"</item>
<item msgid="2762241247228983754">"彩色"</item>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index 6ef2499..a2c3172 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -74,6 +74,8 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Akukho ukuxhumana kuphrinta"</string>
<string name="reason_unknown" msgid="5507940196503246139">"akwaziwa"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"I-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – ayitholakali"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"Sebenzisa i-<xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
+ <string name="print_service_security_warning_summary" msgid="1427434625361692006">"Idokhumenti yakho ingase idlule iseva eyodwa noma amaningi lapho iya kuphrinta."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Okumnyama nokumhlophe"</item>
<item msgid="2762241247228983754">"Umbala"</item>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 7ef5187..eee685f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -379,6 +379,13 @@
@Override
public void onDeviceProvisioned() {
sendUserPresentBroadcast();
+ synchronized (KeyguardViewMediator.this) {
+ // If system user is provisioned, we might want to lock now to avoid showing launcher
+ if (UserManager.isSplitSystemUser()
+ && KeyguardUpdateMonitor.getCurrentUser() == UserHandle.USER_SYSTEM) {
+ doKeyguardLocked(null);
+ }
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index a58bc58..bf5417d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -386,8 +386,8 @@
* Handle screen pinning request.
*/
public final void onBusEvent(final ScreenPinningRequestEvent event) {
- int processUser = event.systemServicesProxy.getProcessUser();
- if (event.systemServicesProxy.isSystemUser(processUser)) {
+ int processUser = sSystemServicesProxy.getProcessUser();
+ if (sSystemServicesProxy.isSystemUser(processUser)) {
mImpl.onStartScreenPinning(event.applicationContext);
} else {
postToSystemUser(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 6874247..58f7124 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -46,6 +46,8 @@
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.LaunchTaskFailedEvent;
+import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
@@ -108,7 +110,7 @@
DozeTrigger mIterateTrigger = new DozeTrigger(500, new Runnable() {
@Override
public void run() {
- boolean dismissed = dismissRecentsToFocusedTask(false);
+ dismissRecentsToFocusedTask(false);
}
});
@@ -569,12 +571,6 @@
/**** RecentsView.RecentsViewCallbacks Implementation ****/
@Override
- public void onTaskLaunchFailed() {
- // Return to Home
- dismissRecentsToHome(true);
- }
-
- @Override
public void onAllTaskViewsDismissed() {
mFinishLaunchHomeRunnable.run();
}
@@ -701,6 +697,17 @@
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_BEHIND);
}
+ public final void onBusEvent(LaunchTaskSucceededEvent event) {
+ MetricsLogger.histogram(this, "overview_task_launch_index", event.taskIndexFromStackFront);
+ }
+
+ public final void onBusEvent(LaunchTaskFailedEvent event) {
+ // Return to Home
+ dismissRecentsToHome(true);
+
+ MetricsLogger.count(this, "overview_task_launch_failed", 1);
+ }
+
public final void onBusEvent(ScreenPinningRequestEvent event) {
MetricsLogger.count(this, "overview_screen_pinned", 1);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index db65e00..4059543 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -503,12 +503,7 @@
MetricsLogger.count(mContext, "overview_affiliated_task_launch", 1);
// Launch the task
- if (toTask.isActive) {
- // Bring an active task to the foreground
- ssp.moveTaskToFront(toTask.key.id, launchOpts);
- } else {
- ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts);
- }
+ ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts);
}
public void showNextAffiliatedTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java
new file mode 100644
index 0000000..3a2d58c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * This is sent when we fail to launch a task.
+ */
+public class LaunchTaskFailedEvent extends EventBus.Event {
+ // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java
new file mode 100644
index 0000000..ec5089f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * This is sent when we successfully launch a task.
+ */
+public class LaunchTaskSucceededEvent extends EventBus.Event {
+
+ public final int taskIndexFromStackFront;
+
+ public LaunchTaskSucceededEvent(int taskIndexFromStackFront) {
+ this.taskIndexFromStackFront = taskIndexFromStackFront;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java
index 5cb4ccf..9d96d8e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java
@@ -26,10 +26,8 @@
public class ScreenPinningRequestEvent extends EventBus.Event {
public final Context applicationContext;
- public final SystemServicesProxy systemServicesProxy;
- public ScreenPinningRequestEvent(Context context, SystemServicesProxy systemServicesProxy) {
+ public ScreenPinningRequestEvent(Context context) {
this.applicationContext = context.getApplicationContext();
- this.systemServicesProxy = systemServicesProxy;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ForegroundThread.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ForegroundThread.java
index 8dc2983..784ac4e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ForegroundThread.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ForegroundThread.java
@@ -28,7 +28,7 @@
private static Handler sHandler;
private ForegroundThread() {
- super("recents.fg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
+ super("recents.fg");
}
private static void ensureThreadLocked() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 62493d6..7b04493 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -130,10 +130,9 @@
? t.taskDescription.getIconFilename() : null;
// Add the task to the stack
- Task task = new Task(taskKey, (t.id != INVALID_TASK_ID), t.affiliatedTaskId,
- t.affiliatedTaskColor, activityLabel, contentDescription, activityIcon,
- activityColor, (i == (taskCount - 1)), config.lockToAppEnabled, icon,
- iconFilename, t.bounds);
+ Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, activityLabel,
+ contentDescription, activityIcon, activityColor, (i == (taskCount - 1)),
+ config.lockToAppEnabled, icon, iconFilename, t.bounds);
task.thumbnail = loader.getAndUpdateThumbnail(taskKey, ssp, false);
if (DEBUG) {
Log.d(TAG, activityLabel + " bounds: " + t.bounds);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 12bd556b..67e18f3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -103,7 +103,6 @@
public int colorPrimary;
public boolean useLightOnPrimaryColor;
public Bitmap thumbnail;
- public boolean isActive;
public boolean lockToThisTask;
public boolean lockToTaskEnabled;
public Bitmap icon;
@@ -116,7 +115,7 @@
// Do nothing
}
- public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,
+ public Task(TaskKey key, int taskAffiliation, int taskAffiliationColor,
String activityTitle, String contentDescription, Drawable activityIcon,
int colorPrimary, boolean lockToThisTask, boolean lockToTaskEnabled, Bitmap icon,
String iconFilename, Rect bounds) {
@@ -131,7 +130,6 @@
this.colorPrimary = hasAffiliationGroupColor ? taskAffiliationColor : colorPrimary;
this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
Color.WHITE) > 3f;
- this.isActive = isActive;
this.lockToThisTask = lockToTaskEnabled && lockToThisTask;
this.lockToTaskEnabled = lockToTaskEnabled;
this.icon = icon;
@@ -149,7 +147,6 @@
this.activityIcon = o.activityIcon;
this.colorPrimary = o.colorPrimary;
this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
- this.isActive = o.isActive;
this.lockToThisTask = o.lockToThisTask;
this.lockToTaskEnabled = o.lockToTaskEnabled;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
new file mode 100644
index 0000000..a28601b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -0,0 +1,331 @@
+/*
+ * 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.views;
+
+import android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.AppTransitionAnimationSpec;
+import android.view.IAppTransitionAnimationSpecsFuture;
+import android.view.WindowManagerGlobal;
+import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
+import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
+import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
+import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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;
+
+/**
+ * A helper class to create transitions to/from Recents
+ */
+public class RecentsTransitionHelper {
+
+ private static final String TAG = "RecentsTransitionHelper";
+ private static final boolean DEBUG = false;
+
+ /**
+ * Special value for {@link #mAppTransitionAnimationSpecs}: Indicate that we are currently
+ * waiting for the specs to be retrieved.
+ */
+ private static final List<AppTransitionAnimationSpec> SPECS_WAITING = new ArrayList<>();
+
+ @GuardedBy("this")
+ private List<AppTransitionAnimationSpec> mAppTransitionAnimationSpecs = SPECS_WAITING;
+
+ private Context mContext;
+ private Handler mHandler;
+ private TaskViewTransform mTmpTransform = new TaskViewTransform();
+
+ private Runnable mStartScreenPinningRunnable = new Runnable() {
+ @Override
+ public void run() {
+ EventBus.getDefault().send(new ScreenPinningRequestEvent(mContext));
+ }
+ };
+
+ public RecentsTransitionHelper(Context context, Handler handler) {
+ mContext = context;
+ mHandler = handler;
+ }
+
+ /**
+ * Launches the specified {@link Task}.
+ */
+ public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
+ final TaskStackView stackView, final TaskView taskView,
+ final boolean lockToTask, final Rect bounds, int destinationStack) {
+ final ActivityOptions opts = ActivityOptions.makeBasic();
+ if (bounds != null) {
+ opts.setBounds(bounds.isEmpty() ? null : bounds);
+ }
+
+ final ActivityOptions.OnAnimationStartedListener animStartedListener;
+ final IAppTransitionAnimationSpecsFuture transitionFuture;
+ if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
+ task.thumbnail.getHeight() > 0) {
+ transitionFuture = getAppTransitionFuture(task, stackView, destinationStack);
+ animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
+ @Override
+ public void onAnimationStarted() {
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+
+ if (lockToTask) {
+ // Request screen pinning after the animation runs
+ mHandler.postDelayed(mStartScreenPinningRunnable, 350);
+ }
+ }
+ };
+ } else {
+ // This is only the case if the task is not on screen (scrolled offscreen for example)
+ transitionFuture = null;
+ animStartedListener = null;
+ }
+
+ if (taskView == null) {
+ // If there is no task view, then we do not need to worry about animating out occluding
+ // task views, and we can launch immediately
+ startTaskActivity(stack, task, taskView, opts, transitionFuture, animStartedListener);
+ } else {
+ if (task.group != null && !task.group.isFrontMostTask(task)) {
+ stackView.startLaunchTaskAnimation(taskView, new Runnable() {
+ @Override
+ public void run() {
+ startTaskActivity(stack, task, taskView, opts, transitionFuture,
+ animStartedListener);
+ }
+ }, lockToTask);
+ } else {
+ stackView.startLaunchTaskAnimation(taskView, null, lockToTask);
+ startTaskActivity(stack, task, taskView, opts, transitionFuture,
+ animStartedListener);
+ }
+ }
+ }
+
+ /**
+ * Starts the activity for the launch task.
+ *
+ * @param taskView this is the {@link TaskView} that we are launching from. This can be null if
+ * we are toggling recents and the launch-to task is now offscreen.
+ */
+ private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskView taskView,
+ ActivityOptions opts, IAppTransitionAnimationSpecsFuture transitionFuture,
+ final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ if (ssp.startActivityFromRecents(mContext, task.key.id, task.activityLabel, opts)) {
+ // Keep track of the index of the task launch
+ int taskIndexFromFront = 0;
+ int taskIndex = stack.indexOfTask(task);
+ if (taskIndex > -1) {
+ taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
+ }
+ EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
+ } else {
+ // Dismiss the task if we fail to launch it
+ EventBus.getDefault().send(new DismissTaskViewEvent(task, taskView));
+
+ // Keep track of failed launches
+ EventBus.getDefault().send(new LaunchTaskFailedEvent());
+ }
+ if (transitionFuture != null) {
+ IRemoteCallback.Stub callback = null;
+ if (animStartedListener != null) {
+ callback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (animStartedListener != null) {
+ animStartedListener.onAnimationStarted();
+ }
+ }
+ });
+ }
+ };
+ }
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .overridePendingAppTransitionMultiThumbFuture(transitionFuture,
+ callback, true /* scaleUp */);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to override transition: " + e);
+ }
+ }
+ }
+
+ /**
+ * Creates a future which will later be queried for animation specs for this current transition.
+ */
+ private IAppTransitionAnimationSpecsFuture getAppTransitionFuture(final Task task,
+ final TaskStackView stackView, final int destinationStack) {
+ return new IAppTransitionAnimationSpecsFuture.Stub() {
+ @Override
+ public AppTransitionAnimationSpec[] get() throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (RecentsTransitionHelper.this) {
+ mAppTransitionAnimationSpecs = composeAnimationSpecs(task, stackView,
+ destinationStack);
+ RecentsTransitionHelper.this.notifyAll();
+ }
+ }
+ });
+ synchronized (RecentsTransitionHelper.this) {
+ while (mAppTransitionAnimationSpecs == SPECS_WAITING) {
+ try {
+ RecentsTransitionHelper.this.wait();
+ } catch (InterruptedException e) {}
+ }
+ if (mAppTransitionAnimationSpecs == null) {
+ return null;
+ }
+ AppTransitionAnimationSpec[] specs
+ = new AppTransitionAnimationSpec[mAppTransitionAnimationSpecs.size()];
+ mAppTransitionAnimationSpecs.toArray(specs);
+ mAppTransitionAnimationSpecs = SPECS_WAITING;
+ return specs;
+ }
+ }
+ };
+ }
+
+ /**
+ * Composes the animation specs for all the tasks in the target stack.
+ */
+ private List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task,
+ final TaskStackView stackView, final int destinationStack) {
+ // Ensure we have a valid target stack id
+ final int targetStackId = destinationStack != INVALID_STACK_ID ?
+ destinationStack : task.key.stackId;
+ if (targetStackId != FREEFORM_WORKSPACE_STACK_ID
+ && targetStackId != FULLSCREEN_WORKSPACE_STACK_ID) {
+ return null;
+ }
+
+ // Calculate the offscreen task rect (for tasks that are not backed by views)
+ float stackScroll = stackView.getScroller().getStackScroll();
+ TaskView taskView = stackView.getChildViewForTask(task);
+ TaskStackLayoutAlgorithm layoutAlgorithm = stackView.getStackAlgorithm();
+ Rect offscreenTaskRect = new Rect(layoutAlgorithm.mTaskRect);
+ offscreenTaskRect.offsetTo(offscreenTaskRect.left,
+ layoutAlgorithm.mCurrentStackRect.bottom);
+
+ // If this is a full screen stack, the transition will be towards the single, full screen
+ // task. We only need the transition spec for this task.
+ List<AppTransitionAnimationSpec> specs = new ArrayList<>();
+ if (targetStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
+ if (taskView == null) {
+ specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
+ } else {
+ layoutAlgorithm.getStackTransform(task, stackScroll, mTmpTransform, null);
+ specs.add(composeAnimationSpec(taskView, mTmpTransform, true /* addHeaderBitmap */));
+ }
+ return specs;
+ }
+
+ // Otherwise, for freeform tasks, create a new animation spec for each task we have to
+ // launch
+ TaskStack stack = stackView.getStack();
+ ArrayList<Task> tasks = stack.getTasks();
+ int taskCount = tasks.size();
+ for (int i = taskCount - 1; i >= 0; i--) {
+ Task t = tasks.get(i);
+ if (t.isFreeformTask()) {
+ TaskView tv = stackView.getChildViewForTask(t);
+ if (tv == null) {
+ // TODO: Create a different animation task rect for this case (though it should
+ // never happen)
+ specs.add(composeOffscreenAnimationSpec(t, offscreenTaskRect));
+ } else {
+ layoutAlgorithm.getStackTransform(task, stackScroll, mTmpTransform, null);
+ specs.add(composeAnimationSpec(tv, mTmpTransform, true /* addHeaderBitmap */));
+ }
+ }
+ }
+
+ return specs;
+ }
+
+ /**
+ * Composes a single animation spec for the given {@link Task}
+ */
+ private static AppTransitionAnimationSpec composeOffscreenAnimationSpec(Task task,
+ Rect taskRect) {
+ return new AppTransitionAnimationSpec(task.key.id, null, taskRect);
+ }
+
+ /**
+ * Composes a single animation spec for the given {@link TaskView}
+ */
+ private static AppTransitionAnimationSpec composeAnimationSpec(TaskView taskView,
+ TaskViewTransform transform, boolean addHeaderBitmap) {
+ // Disable any focused state before we draw the header
+ // Upfront the processing of the thumbnail
+ if (taskView.isFocusedTask()) {
+ taskView.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
+ }
+
+ Bitmap b = null;
+ if (addHeaderBitmap) {
+ float scale = transform.scale;
+ int fromHeaderWidth = (int) (taskView.mHeaderView.getMeasuredWidth() * scale);
+ int fromHeaderHeight = (int) (taskView.mHeaderView.getMeasuredHeight() * scale);
+ b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
+ Bitmap.Config.ARGB_8888);
+
+ if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+ b.eraseColor(0xFFff0000);
+ } else {
+ Canvas c = new Canvas(b);
+ c.scale(scale, scale);
+ taskView.mHeaderView.draw(c);
+ c.setBitmap(null);
+ }
+ b = b.createAshmemBitmap();
+ }
+
+ Rect taskRect = new Rect();
+ transform.rect.round(taskRect);
+ return new AppTransitionAnimationSpec(taskView.getTask().key.id, b, taskRect);
+ }
+}
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 af30268..e37b7dc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,45 +16,31 @@
package com.android.systemui.recents.views;
-import android.app.ActivityOptions;
-import android.app.ActivityOptions.OnAnimationStartedListener;
import android.content.Context;
-import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.IRemoteCallback;
-import android.os.RemoteException;
+import android.os.Handler;
import android.util.ArraySet;
import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
import android.view.AppTransitionAnimationSpec;
-import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
-import android.view.WindowManagerGlobal;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
-
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
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;
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;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
@@ -65,8 +51,6 @@
import java.util.ArrayList;
import java.util.List;
-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;
/**
@@ -78,29 +62,22 @@
private static final String TAG = "RecentsView";
private static final boolean DEBUG = false;
- private static final boolean ADD_HEADER_BITMAP = true;
-
- /**
- * Special value for {@link #mAppTransitionAnimationSpecs}: Indicate that we are currently
- * waiting for the specs to be retrieved.
- */
- private static final List<AppTransitionAnimationSpec> SPECS_WAITING = new ArrayList<>();
-
private int mStackViewVisibility = View.VISIBLE;
/** The RecentsView callbacks */
public interface RecentsViewCallbacks {
- public void onTaskLaunchFailed();
public void onAllTaskViewsDismissed();
}
LayoutInflater mInflater;
+ Handler mHandler;
ArrayList<TaskStack> mStacks;
TaskStackView mTaskStackView;
RecentsAppWidgetHostView mSearchBar;
RecentsViewCallbacks mCb;
+ RecentsTransitionHelper mTransitionHelper;
RecentsViewTouchHandler mTouchHandler;
DragView mDragView;
TaskStack.DockState[] mVisibleDockStates = {
@@ -114,10 +91,6 @@
Rect mSystemInsets = new Rect();
-
- @GuardedBy("this")
- List<AppTransitionAnimationSpec> mAppTransitionAnimationSpecs = SPECS_WAITING;
-
public RecentsView(Context context) {
super(context);
}
@@ -134,6 +107,8 @@
super(context, attrs, defStyleAttr, defStyleRes);
setWillNotDraw(false);
mInflater = LayoutInflater.from(context);
+ mHandler = new Handler();
+ mTransitionHelper = new RecentsTransitionHelper(getContext(), mHandler);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
mTouchHandler = new RecentsViewTouchHandler(this);
@@ -201,7 +176,7 @@
Task task = mTaskStackView.getFocusedTask();
if (task != null) {
TaskView taskView = mTaskStackView.getChildViewForTask(task);
- onTaskViewClicked(mTaskStackView, taskView, stack, task, false, false, null,
+ onTaskViewClicked(mTaskStackView, taskView, stack, task, false, null,
INVALID_STACK_ID);
return true;
}
@@ -219,7 +194,7 @@
for (int j = 0; j < taskViewCount; j++) {
TaskView tv = taskViews.get(j);
if (tv.getTask() == task) {
- onTaskViewClicked(mTaskStackView, tv, stack, task, false, taskBounds != null,
+ onTaskViewClicked(mTaskStackView, tv, stack, task, false,
taskBounds, destinationStack);
return true;
}
@@ -424,282 +399,14 @@
}
}
- private IAppTransitionAnimationSpecsFuture getAppTransitionFuture(final TaskStackView stackView,
- final TaskView clickedTask, final int offsetX, final int offsetY,
- final float stackScroll, final int destinationStack) {
- return new IAppTransitionAnimationSpecsFuture.Stub() {
- @Override
- public AppTransitionAnimationSpec[] get() throws RemoteException {
- post(new Runnable() {
- @Override
- public void run() {
- synchronized (RecentsView.this) {
- mAppTransitionAnimationSpecs = getAppTransitionAnimationSpecs(stackView,
- clickedTask, offsetX, offsetY, stackScroll, destinationStack);
- RecentsView.this.notifyAll();
- }
- }
- });
- synchronized (RecentsView.this) {
- while (mAppTransitionAnimationSpecs == SPECS_WAITING) {
- try {
- RecentsView.this.wait();
- } catch (InterruptedException e) {}
- }
- if (mAppTransitionAnimationSpecs == null) {
- return null;
- }
- AppTransitionAnimationSpec[] specs
- = new AppTransitionAnimationSpec[mAppTransitionAnimationSpecs.size()];
- mAppTransitionAnimationSpecs.toArray(specs);
- mAppTransitionAnimationSpecs = SPECS_WAITING;
- return specs;
- }
- }
- };
- }
-
- private List<AppTransitionAnimationSpec> getAppTransitionAnimationSpecs(TaskStackView stackView,
- TaskView clickedTask, int offsetX, int offsetY, float stackScroll,
- int destinationStack) {
- final int targetStackId = destinationStack != INVALID_STACK_ID ?
- destinationStack : clickedTask.getTask().key.stackId;
- if (targetStackId != FREEFORM_WORKSPACE_STACK_ID
- && targetStackId != FULLSCREEN_WORKSPACE_STACK_ID) {
- return null;
- }
- // If this is a full screen stack, the transition will be towards the single, full screen
- // task. We only need the transition spec for this task.
- List<AppTransitionAnimationSpec> specs = new ArrayList<>();
- if (targetStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
- specs.add(createThumbnailHeaderAnimationSpec(
- stackView, offsetX, offsetY, stackScroll, clickedTask,
- clickedTask.getTask().key.id, ADD_HEADER_BITMAP));
- return specs;
- }
- // This is a free form stack or full screen stack, so there will be multiple windows
- // animating from thumbnails. We need transition animation specs for all of them.
-
- // We will use top and bottom task views as a base for tasks, that aren't visible on the
- // screen. This is necessary for cascade recents list, where some of the tasks might be
- // hidden.
- List<TaskView> taskViews = stackView.getTaskViews();
- int childCount = taskViews.size();
- TaskView topChild = taskViews.get(0);
- TaskView bottomChild = taskViews.get(childCount - 1);
- SparseArray<TaskView> taskViewsByTaskId = new SparseArray<>();
- for (int i = 0; i < childCount; i++) {
- TaskView taskView = taskViews.get(i);
- taskViewsByTaskId.put(taskView.getTask().key.id, taskView);
- }
-
- TaskStack stack = stackView.getStack();
- // We go through all tasks now and for each generate transition animation spec. If there is
- // a view associated with a task, we use that view as a base for the animation. If there
- // isn't, we use bottom or top view, depending on which one would be closer to the task
- // view if it existed.
- ArrayList<Task> tasks = stack.getTasks();
- boolean passedClickedTask = false;
- for (int i = 0, n = tasks.size(); i < n; i++) {
- Task task = tasks.get(i);
- TaskView taskView = taskViewsByTaskId.get(task.key.id);
- if (taskView != null) {
- specs.add(createThumbnailHeaderAnimationSpec(stackView, offsetX, offsetY,
- stackScroll, taskView, taskView.getTask().key.id, ADD_HEADER_BITMAP));
- if (taskView == clickedTask) {
- passedClickedTask = true;
- }
- } else {
- taskView = passedClickedTask ? bottomChild : topChild;
- specs.add(createThumbnailHeaderAnimationSpec(stackView, offsetX, offsetY,
- stackScroll, taskView, task.key.id, !ADD_HEADER_BITMAP));
- }
- }
-
- return specs;
- }
-
- private AppTransitionAnimationSpec createThumbnailHeaderAnimationSpec(TaskStackView stackView,
- int offsetX, int offsetY, float stackScroll, TaskView tv, int taskId,
- boolean addHeaderBitmap) {
- // Disable any focused state before we draw the header
- // Upfront the processing of the thumbnail
- if (tv.isFocusedTask()) {
- tv.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
- }
- TaskViewTransform transform = new TaskViewTransform();
- transform = stackView.getStackAlgorithm().getStackTransform(tv.mTask, stackScroll,
- transform, null);
-
- float scale = tv.getScaleX();
- int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
- int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
-
- Bitmap b = null;
- if (addHeaderBitmap) {
- b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
- Bitmap.Config.ARGB_8888);
-
- if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
- b.eraseColor(0xFFff0000);
- } else {
- Canvas c = new Canvas(b);
- c.scale(tv.getScaleX(), tv.getScaleY());
- tv.mHeaderView.draw(c);
- c.setBitmap(null);
-
- }
- b = b.createAshmemBitmap();
- }
-
- int[] pts = new int[2];
- tv.getLocationOnScreen(pts);
-
- final int left = pts[0] + offsetX;
- final int top = pts[1] + offsetY;
- final Rect rect = new Rect(left, top, left + (int) transform.rect.width(),
- top + (int) transform.rect.height());
-
- return new AppTransitionAnimationSpec(taskId, b, rect);
- }
-
/**** 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) {
-
- // Upfront the processing of the thumbnail
- TaskViewTransform transform = new TaskViewTransform();
- View sourceView;
- int offsetX = 0;
- int offsetY = 0;
- float stackScroll = stackView.getScroller().getStackScroll();
- if (tv == null) {
- // If there is no actual task view, then use the stack view as the source view
- // and then offset to the expected transform rect, but bound this to just
- // outside the display rect (to ensure we don't animate from too far away)
- sourceView = stackView;
- offsetX = (int) transform.rect.left;
- offsetY = getMeasuredHeight();
- } else {
- sourceView = tv.mThumbnailView;
- }
-
- // Compute the thumbnail to scale up from
- final SystemServicesProxy ssp = Recents.getSystemServices();
- boolean screenPinningRequested = false;
- ActivityOptions opts = ActivityOptions.makeBasic();
- ActivityOptions.OnAnimationStartedListener animStartedListener = null;
- final IAppTransitionAnimationSpecsFuture transitionFuture;
- if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
- task.thumbnail.getHeight() > 0) {
- animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
- @Override
- public void onAnimationStarted() {
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
-
- if (lockToTask) {
- // Request screen pinning after the animation runs
- postDelayed(new Runnable() {
- @Override
- public void run() {
- EventBus.getDefault().send(new ScreenPinningRequestEvent(
- getContext(), ssp));
- }
- }, 350);
- }
- }
- };
- transitionFuture = getAppTransitionFuture(stackView, tv, offsetX, offsetY, stackScroll,
- destinationStack);
- screenPinningRequested = true;
- } else {
- transitionFuture = null;
- }
- if (boundsValid) {
- opts.setBounds(bounds.isEmpty() ? null : bounds);
- }
- final ActivityOptions launchOpts = opts;
- final boolean finalScreenPinningRequested = screenPinningRequested;
- final OnAnimationStartedListener finalAnimStartedListener = animStartedListener;
- final Runnable launchRunnable = new Runnable() {
- @Override
- public void run() {
- if (task.isActive) {
- // Bring an active task to the foreground
- ssp.moveTaskToFront(task.key.id, launchOpts);
- } else {
- if (ssp.startActivityFromRecents(getContext(), task.key.id, task.activityLabel,
- launchOpts)) {
- if (!finalScreenPinningRequested) {
- // If we have not requested this already to be run after the window
- // transition, then just run it now
- EventBus.getDefault().send(new ScreenPinningRequestEvent(
- getContext(), ssp));
- }
- } else {
- // Dismiss the task and return the user to home if we fail to
- // launch the task
- EventBus.getDefault().send(new DismissTaskViewEvent(task, tv));
- if (mCb != null) {
- mCb.onTaskLaunchFailed();
- }
-
- // Keep track of failed launches
- MetricsLogger.count(getContext(), "overview_task_launch_failed", 1);
- }
- }
- if (transitionFuture != null) {
- IRemoteCallback.Stub callback = new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) throws RemoteException {
- post(new Runnable() {
- @Override
- public void run() {
- if (finalAnimStartedListener != null) {
- finalAnimStartedListener.onAnimationStarted();
- }
- }
- });
- }
- };
- try {
- WindowManagerGlobal.getWindowManagerService()
- .overridePendingAppTransitionMultiThumbFuture(transitionFuture,
- callback, true /* scaleUp */);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to override transition: " + e);
- }
- }
- }
- };
-
- // Keep track of the index of the task launch
- int taskIndexFromFront = 0;
- int taskIndex = stack.indexOfTask(task);
- if (taskIndex > -1) {
- taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
- }
- MetricsLogger.histogram(getContext(), "overview_task_launch_index", taskIndexFromFront);
-
- // Launch the app right away if there is no task view, otherwise, animate the icon out first
- if (tv == null) {
- launchRunnable.run();
- } else {
- if (task.group != null && !task.group.isFrontMostTask(task)) {
- // For affiliated tasks that are behind other tasks, we must animate the front cards
- // out of view before starting the task transition
- stackView.startLaunchTaskAnimation(tv, launchRunnable, lockToTask);
- } else {
- // Otherwise, we can start the task transition immediately
- stackView.startLaunchTaskAnimation(tv, null, lockToTask);
- launchRunnable.run();
- }
- }
+ final Rect bounds, int destinationStack) {
+ mTransitionHelper.launchTaskFromRecents(stack, task, stackView, tv, lockToTask, bounds,
+ destinationStack);
}
@Override
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 4a11b93..9c8829f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -79,7 +79,7 @@
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
- boolean lockToTask, boolean boundsValid, Rect bounds, int destinationStack);
+ boolean lockToTask, Rect bounds, int destinationStack);
public void onAllTaskViewsDismissed(ArrayList<Task> removedTasks);
public void onTaskStackFilterTriggered();
public void onTaskStackUnfilterTriggered();
@@ -1346,8 +1346,7 @@
mUIDozeTrigger.stopDozing();
if (mCb != null) {
- mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask, false, null,
- INVALID_STACK_ID);
+ mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask, null, INVALID_STACK_ID);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 94809bc..0d3f803 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -49,8 +49,29 @@
mTmpRect.set(mResizeRect);
}
try {
- ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID,
- mTmpRect, true);
+ ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, mTmpRect, true);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to resize stack: " + e);
+ }
+ }
+ };
+
+ private final Runnable mDismissRunnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ActivityManagerNative.getDefault().removeStack(DOCKED_STACK_ID);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to remove stack: " + e);
+ }
+ }
+ };
+
+ private final Runnable mMaximizeRunnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, null, true);
} catch (RemoteException e) {
Log.w(TAG, "Failed to resize stack: " + e);
}
@@ -65,27 +86,24 @@
}
public void dismissDockedStack() {
- try {
- ActivityManagerNative.getDefault().removeStack(DOCKED_STACK_ID);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to remove stack: " + e);
- }
+ mExecutor.execute(mDismissRunnable);
}
public void maximizeDockedStack() {
- try {
- ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, null, true);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to resize stack: " + e);
- }
+ mExecutor.execute(mMaximizeRunnable);
}
- public void setResizing(boolean resizing) {
- try {
- WindowManagerGlobal.getWindowManagerService().setDockedStackResizing(resizing);
- } catch (RemoteException e) {
- Log.w(TAG, "Error calling setDockedStackResizing: " + e);
- }
+ public void setResizing(final boolean resizing) {
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ WindowManagerGlobal.getWindowManagerService().setDockedStackResizing(resizing);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling setDockedStackResizing: " + e);
+ }
+ }
+ });
}
public int getDockSide() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
index a51f62a..58c9722 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
@@ -1060,7 +1060,7 @@
ris = packageManager.queryIntentActivitiesAsUser(intentToResolve, 0, userId);
}
if (ris == null || ris.size() <= 0) {
- Slog.e(TAG, "Failed to build intent for " + packageName);
+ Slog.i(TAG, "Failed to build intent for " + packageName);
return null;
}
return new ComponentName(ris.get(0).activityInfo.packageName,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
index d527f29..76a9798 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
@@ -179,7 +179,7 @@
}
}
- Slog.e(TAG, "Activity doesn't have category Intent.CATEGORY_LAUNCHER " + component);
+ Slog.i(TAG, "Activity doesn't have category Intent.CATEGORY_LAUNCHER " + component);
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
index 18db5b8..512af1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
@@ -19,16 +19,13 @@
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.content.Context;
-import android.graphics.drawable.RippleDrawable;
-import android.os.Handler;
-import android.os.Message;
import android.util.AttributeSet;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-
import com.android.keyguard.AlphaOptimizedImageButton;
public class SettingsButton extends AlphaOptimizedImageButton {
@@ -157,6 +154,7 @@
protected void startContinuousSpin() {
cancelAnimation();
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
mUpToSpeed = true;
mAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, 0, 360);
mAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 911d6a2..dc7c967 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -16,9 +16,10 @@
package com.android.systemui.tuner;
import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
@@ -33,7 +34,6 @@
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
-
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
@@ -51,6 +51,8 @@
public static final String SETTING_SEEN_TUNER_WARNING = "seen_tuner_warning";
+ private static final String WARNING_TAG = "tuner_warning";
+
private static final int MENU_REMOVE = Menu.FIRST + 1;
private final SettingObserver mSettingObserver = new SettingObserver();
@@ -90,16 +92,9 @@
mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT);
if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,
0) == 0) {
- new AlertDialog.Builder(getContext())
- .setTitle(R.string.tuner_warning_title)
- .setMessage(R.string.tuner_warning)
- .setPositiveButton(R.string.got_it, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Settings.Secure.putInt(getContext().getContentResolver(),
- SETTING_SEEN_TUNER_WARNING, 1);
- }
- }).show();
+ if (getFragmentManager().findFragmentByTag(WARNING_TAG) == null) {
+ new TunerWarningFragment().show(getFragmentManager(), WARNING_TAG);
+ }
}
TunerService.get(getContext()).addTunable(mQsPaging, QSPanel.QS_THE_NEW_QS);
}
@@ -187,4 +182,20 @@
mQsTuner.setEnabled(newValue == null || Integer.parseInt(newValue) == 0);
}
};
+
+ public static class TunerWarningFragment extends DialogFragment {
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getContext())
+ .setTitle(R.string.tuner_warning_title)
+ .setMessage(R.string.tuner_warning)
+ .setPositiveButton(R.string.got_it, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Settings.Secure.putInt(getContext().getContentResolver(),
+ SETTING_SEEN_TUNER_WARNING, 1);
+ }
+ }).show();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 71559389..1e3b0f1 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -116,8 +116,12 @@
public void reloadSetting(Uri uri) {
String key = mListeningUris.get(uri);
+ List<Tunable> tunables = mTunableLookup.get(key);
+ if (tunables == null) {
+ return;
+ }
String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
- for (Tunable tunable : mTunableLookup.get(key)) {
+ for (Tunable tunable : tunables) {
tunable.onTuningChanged(key, value);
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2820216..30565c6 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1527,7 +1527,7 @@
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
- mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
+ mAm.notifyPackageUse(r.serviceInfo.packageName);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0cf58b1..2b776b9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -55,6 +55,8 @@
import android.app.IAppTask;
import android.app.ITaskStackListener;
import android.app.ProfilerInfo;
+import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.IDevicePolicyManager;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.usage.UsageEvents;
@@ -502,11 +504,6 @@
*/
SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
- /**
- * The package name of the DeviceOwner. This package is not permitted to have its data cleared.
- */
- String mDeviceOwnerName;
-
final UserController mUserController;
public class PendingAssistExtras extends Binder implements Runnable {
@@ -3062,12 +3059,10 @@
return proc;
}
- void ensurePackageDexOpt(String packageName) {
+ void notifyPackageUse(String packageName) {
IPackageManager pm = AppGlobals.getPackageManager();
try {
- if (pm.performDexOptIfNeeded(packageName, null /* instruction set */)) {
- mDidDexOpt = true;
- }
+ pm.notifyPackageUse(packageName);
} catch (RemoteException e) {
}
}
@@ -5139,8 +5134,12 @@
public boolean clearApplicationUserData(final String packageName,
final IPackageDataObserver observer, int userId) {
enforceNotIsolatedCaller("clearApplicationUserData");
- if (packageName != null && packageName.equals(mDeviceOwnerName)) {
- throw new SecurityException("Clearing DeviceOwner data is forbidden.");
+
+ final DevicePolicyManagerInternal dpmi =
+ LocalServices.getService(DevicePolicyManagerInternal.class);
+ if (dpmi != null && dpmi.isDeviceAdminPackage(userId, packageName)) {
+ throw new SecurityException(
+ "Clearing DeviceAdmin/DeviceOwner/ProfileOwner data is forbidden.");
}
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
@@ -6136,11 +6135,11 @@
|| (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
}
- ensurePackageDexOpt(app.instrumentationInfo != null
+ notifyPackageUse(app.instrumentationInfo != null
? app.instrumentationInfo.packageName
: app.info.packageName);
if (app.instrumentationClass != null) {
- ensurePackageDexOpt(app.instrumentationClass.getPackageName());
+ notifyPackageUse(app.instrumentationClass.getPackageName());
}
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc "
+ processName + " with config " + mConfiguration);
@@ -6220,7 +6219,7 @@
if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {
if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
"New app is backup target, launching agent for " + app);
- ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
+ notifyPackageUse(mBackupTarget.appInfo.packageName);
try {
thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
@@ -9241,17 +9240,6 @@
}
@Override
- public void updateDeviceOwner(String packageName) {
- final int callingUid = Binder.getCallingUid();
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
- throw new SecurityException("updateDeviceOwner called from non-system process");
- }
- synchronized (this) {
- mDeviceOwnerName = packageName;
- }
- }
-
- @Override
public void updateLockTaskPackages(int userId, String[] packages) {
final int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
@@ -9472,7 +9460,7 @@
app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.versionCode,
mProcessStats);
}
- ensurePackageDexOpt(cpi.applicationInfo.packageName);
+ notifyPackageUse(cpi.applicationInfo.packageName);
}
}
return providers;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 400ebc6..ba6e9b1c 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4611,14 +4611,20 @@
voiceInteractor);
// add the task to stack first, mTaskPositioner might need the stack association
addTask(task, toTop, false);
- if (mTaskPositioner != null) {
- mTaskPositioner.updateDefaultBounds(task, mTaskHistory, info.layout);
- } else if (mBounds != null && task.mResizeable) {
+ if (!layoutTaskInStack(task, info.layout) && mBounds != null && task.mResizeable) {
task.updateOverrideConfiguration(mBounds);
}
return task;
}
+ boolean layoutTaskInStack(TaskRecord task, ActivityInfo.Layout layout) {
+ if (mTaskPositioner == null) {
+ return false;
+ }
+ mTaskPositioner.updateDefaultBounds(task, mTaskHistory, layout);
+ return true;
+ }
+
ArrayList<TaskRecord> getAllTasks() {
return new ArrayList<>(mTaskHistory);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6acaa77..4fc8454 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1294,7 +1294,7 @@
// Home process is the root process of the task.
mService.mHomeProcess = task.mActivities.get(0).app;
}
- mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
+ mService.notifyPackageUse(r.intent.getComponent().getPackageName());
r.sleeping = false;
r.forceNewConfig = false;
mService.showAskCompatModeDialogLocked(r);
@@ -3420,9 +3420,12 @@
Slog.w(TAG, "positionTaskInStackLocked: no task for id=" + taskId);
return;
}
- ActivityStack stack =
- getStack(stackId, CREATE_IF_NEEDED, !ON_TOP);
- mWindowManager.positionTaskInStack(taskId, stackId, position);
+ final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, !ON_TOP);
+
+ task.updateOverrideConfigurationForStack(stack);
+
+ mWindowManager.positionTaskInStack(
+ taskId, stackId, position, task.mBounds, task.mOverrideConfig);
final boolean stackChanged = task.stack != null && task.stack != stack;
if (stackChanged) {
task.stack.removeTask(task, "moveTaskToStack", MOVING);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 6de8579..d317791 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -269,7 +269,7 @@
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"Delivering to component " + r.curComponent
+ ": " + r);
- mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
+ mService.notifyPackageUse(r.intent.getComponent().getPackageName());
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 22c3025..096c85e 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1282,6 +1282,31 @@
return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
}
+ /** Updates the task's bounds and override configuration to match what is expected for the
+ * input stack. */
+ void updateOverrideConfigurationForStack(ActivityStack inStack) {
+ if (stack != null && stack == inStack) {
+ return;
+ }
+
+ if (inStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ if (!mResizeable) {
+ throw new IllegalArgumentException("Can not position non-resizeable task="
+ + this + " in stack=" + inStack);
+ }
+ if (mBounds != null) {
+ return;
+ }
+ if (mLastNonFullscreenBounds != null) {
+ updateOverrideConfiguration(mLastNonFullscreenBounds);
+ } else {
+ inStack.layoutTaskInStack(this, null);
+ }
+ } else {
+ updateOverrideConfiguration(inStack.mBounds);
+ }
+ }
+
/**
* Returns the correct stack to use based on task type and currently set bounds,
* regardless of the focused stack and current stack association of the task.
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 7b1ac5ca..af20679 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -28,6 +28,7 @@
import android.util.Log;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.TimeUnit;
/**
* {@hide}
@@ -55,6 +56,7 @@
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
.setMinimumLatency(minLatency)
+ .setPeriodic(TimeUnit.DAYS.toMillis(1))
.build();
js.schedule(job);
}
@@ -89,7 +91,7 @@
// skip previously failing package
continue;
}
- if (!pm.performDexOpt(pkg, null /* instruction set */, true)) {
+ if (!pm.performDexOpt(pkg, null /* instruction set */)) {
// there was a problem running dexopt,
// remember this so we do not keep retrying.
sFailedPackageNames.add(pkg);
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 56c4fb1..d29a623 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -55,7 +55,6 @@
static final int DEX_OPT_FAILED = -1;
private final PackageManagerService mPackageManagerService;
- private ArraySet<PackageParser.Package> mDeferredDexOpt;
private final PowerManager.WakeLock mDexoptWakeLock;
private volatile boolean mSystemReady;
@@ -75,8 +74,7 @@
* {@link PackageManagerService#mInstallLock}.
*/
int performDexOpt(PackageParser.Package pkg, String[] instructionSets,
- boolean forceDex, boolean defer, boolean inclDependencies,
- boolean bootComplete, boolean useJit) {
+ boolean inclDependencies) {
ArraySet<String> done;
if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
done = new ArraySet<String>();
@@ -91,8 +89,7 @@
mDexoptWakeLock.acquire();
}
try {
- return performDexOptLI(pkg, instructionSets, forceDex, defer, bootComplete,
- useJit, done);
+ return performDexOptLI(pkg, instructionSets, done);
} finally {
if (useLock) {
mDexoptWakeLock.release();
@@ -102,7 +99,6 @@
}
private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
- boolean forceDex, boolean defer, boolean bootComplete, boolean useJit,
ArraySet<String> done) {
final String[] instructionSets = targetInstructionSets != null ?
targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
@@ -110,12 +106,10 @@
if (done != null) {
done.add(pkg.packageName);
if (pkg.usesLibraries != null) {
- performDexOptLibsLI(pkg.usesLibraries, instructionSets, forceDex, defer,
- bootComplete, useJit, done);
+ performDexOptLibsLI(pkg.usesLibraries, instructionSets, done);
}
if (pkg.usesOptionalLibraries != null) {
- performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSets, forceDex, defer,
- bootComplete, useJit, done);
+ performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSets, done);
}
}
@@ -134,30 +128,18 @@
// 3.) we are skipping an unneeded dexopt
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- if (!forceDex && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) {
+ if (pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) {
continue;
}
for (String path : paths) {
final int dexoptNeeded;
- if (forceDex) {
- dexoptNeeded = DexFile.DEX2OAT_NEEDED;
- } else {
- try {
- dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
- dexCodeInstructionSet, defer);
- } catch (IOException ioe) {
- Slog.w(TAG, "IOException reading apk: " + path, ioe);
- return DEX_OPT_FAILED;
- }
- }
-
- if (!forceDex && defer && dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- // We're deciding to defer a needed dexopt. Don't bother dexopting for other
- // paths and instruction sets. We'll deal with them all together when we process
- // our list of deferred dexopts.
- addPackageForDeferredDexopt(pkg);
- return DEX_OPT_DEFERRED;
+ try {
+ dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
+ dexCodeInstructionSet, /* defer */false);
+ } catch (IOException ioe) {
+ Slog.w(TAG, "IOException reading apk: " + path, ioe);
+ return DEX_OPT_FAILED;
}
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
@@ -177,20 +159,17 @@
Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+ pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
- + " oatDir = " + oatDir + " bootComplete=" + bootComplete
- + " useJit=" + useJit);
+ + " oatDir = " + oatDir);
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
final int dexFlags =
(!pkg.isForwardLocked() ? DEXOPT_PUBLIC : 0)
| (vmSafeMode ? DEXOPT_SAFEMODE : 0)
| (debuggable ? DEXOPT_DEBUGGABLE : 0)
- | (bootComplete ? DEXOPT_BOOTCOMPLETE : 0)
- | (useJit ? DEXOPT_USEJIT : 0);
+ | DEXOPT_BOOTCOMPLETE;
final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
pkg.packageName, dexCodeInstructionSet, dexoptNeeded, oatDir, dexFlags);
- // Dex2oat might fail due to compiler / verifier errors. We soldier on
- // regardless, and attempt to interpret the app as a safety net.
+ // Dex2oat might fail due to compiler / verifier errors.
if (ret == 0) {
performedDexOpt = true;
}
@@ -243,34 +222,16 @@
}
private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets,
- boolean forceDex, boolean defer, boolean bootComplete, boolean useJit,
ArraySet<String> done) {
for (String libName : libs) {
PackageParser.Package libPkg = mPackageManagerService.findSharedNonSystemLibrary(
libName);
if (libPkg != null && !done.contains(libName)) {
- performDexOptLI(libPkg, instructionSets, forceDex, defer, bootComplete, useJit, done);
+ performDexOptLI(libPkg, instructionSets, done);
}
}
}
- /**
- * Clears set of deferred dexopt packages.
- * @return content of dexopt set if it was not empty
- */
- public ArraySet<PackageParser.Package> clearDeferredDexOptPackages() {
- ArraySet<PackageParser.Package> result = mDeferredDexOpt;
- mDeferredDexOpt = null;
- return result;
- }
-
- public void addPackageForDeferredDexopt(PackageParser.Package pkg) {
- if (mDeferredDexOpt == null) {
- mDeferredDexOpt = new ArraySet<>();
- }
- mDeferredDexOpt.add(pkg);
- }
-
void systemReady() {
mSystemReady = true;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d7664ab..ad1cbe6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -429,8 +429,6 @@
final Context mContext;
final boolean mFactoryTest;
final boolean mOnlyCore;
- final boolean mLazyDexOpt;
- final long mDexOptLRUThresholdInMills;
final DisplayMetrics mMetrics;
final int mDefParseFlags;
final String[] mSeparateProcesses;
@@ -1856,7 +1854,6 @@
mContext = context;
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
- mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
mMetrics = new DisplayMetrics();
mSettings = new Settings(mPackages);
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
@@ -1872,15 +1869,6 @@
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
- // TODO: add a property to control this?
- long dexOptLRUThresholdInMinutes;
- if (mLazyDexOpt) {
- dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
- } else {
- dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
- }
- mDexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
-
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
@@ -1975,31 +1963,14 @@
// scanning install directories.
final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
- final ArraySet<String> alreadyDexOpted = new ArraySet<String>();
-
- /**
- * Add everything in the in the boot class path to the
- * list of process files because dexopt will have been run
- * if necessary during zygote startup.
- */
final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
- if (bootClassPath != null) {
- String[] bootClassPathElements = splitString(bootClassPath, ':');
- for (String element : bootClassPathElements) {
- alreadyDexOpted.add(element);
- }
- } else {
+ if (bootClassPath == null) {
Slog.w(TAG, "No BOOTCLASSPATH found!");
}
- if (systemServerClassPath != null) {
- String[] systemServerClassPathElements = splitString(systemServerClassPath, ':');
- for (String element : systemServerClassPathElements) {
- alreadyDexOpted.add(element);
- }
- } else {
+ if (systemServerClassPath == null) {
Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
}
@@ -2026,7 +1997,6 @@
try {
int dexoptNeeded = DexFile.getDexOptNeeded(lib, null, dexCodeInstructionSet, false);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- alreadyDexOpted.add(lib);
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/);
}
@@ -2042,52 +2012,6 @@
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
- // Gross hack for now: we know this file doesn't contain any
- // code, so don't dexopt it to avoid the resulting log spew.
- alreadyDexOpted.add(frameworkDir.getPath() + "/framework-res.apk");
-
- // Gross hack for now: we know this file is only part of
- // the boot class path for art, so don't dexopt it to
- // avoid the resulting log spew.
- alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar");
-
- /**
- * There are a number of commands implemented in Java, which
- * we currently need to do the dexopt on so that they can be
- * run from a non-root shell.
- */
- String[] frameworkFiles = frameworkDir.list();
- if (frameworkFiles != null) {
- // TODO: We could compile these only for the most preferred ABI. We should
- // first double check that the dex files for these commands are not referenced
- // by other system apps.
- for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- for (int i=0; i<frameworkFiles.length; i++) {
- File libPath = new File(frameworkDir, frameworkFiles[i]);
- String path = libPath.getPath();
- // Skip the file if we already did it.
- if (alreadyDexOpted.contains(path)) {
- continue;
- }
- // Skip the file if it is not a type we want to dexopt.
- if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
- continue;
- }
- try {
- int dexoptNeeded = DexFile.getDexOptNeeded(path, null, dexCodeInstructionSet, false);
- if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- mInstaller.dexopt(path, Process.SYSTEM_UID, dexCodeInstructionSet,
- dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/);
- }
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Jar not found: " + path);
- } catch (IOException e) {
- Slog.w(TAG, "Exception reading jar: " + path, e);
- }
- }
- }
- }
-
final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
// when upgrading from pre-M, promote system app permissions from install to runtime
@@ -2306,7 +2230,6 @@
// the rest of the commands above) because there's precious little we
// can do about it. A settings error is reported, though.
adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
- false /* force dexopt */, false /* defer dexopt */,
false /* boot complete */);
}
@@ -6148,8 +6071,8 @@
}
@Override
- public void performBootDexOpt() {
- enforceSystemOrRoot("Only the system can request dexopt be performed");
+ public void performFstrimIfNeeded() {
+ enforceSystemOrRoot("Only the system can request fstrim");
// Before everything else, see whether we need to fstrim.
try {
@@ -6190,98 +6113,6 @@
} catch (RemoteException e) {
// Can't happen; MountService is local
}
-
- final ArraySet<PackageParser.Package> pkgs;
- synchronized (mPackages) {
- pkgs = mPackageDexOptimizer.clearDeferredDexOptPackages();
- }
-
- if (pkgs != null) {
- // Sort apps by importance for dexopt ordering. Important apps are given more priority
- // in case the device runs out of space.
- ArrayList<PackageParser.Package> sortedPkgs = new ArrayList<PackageParser.Package>();
- // Give priority to core apps.
- for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
- PackageParser.Package pkg = it.next();
- if (pkg.coreApp) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding core app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- it.remove();
- }
- }
- // Give priority to system apps that listen for pre boot complete.
- Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
- ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
- for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
- PackageParser.Package pkg = it.next();
- if (pkgNames.contains(pkg.packageName)) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding pre boot system app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- it.remove();
- }
- }
- // Filter out packages that aren't recently used.
- filterRecentlyUsedApps(pkgs);
- // Add all remaining apps.
- for (PackageParser.Package pkg : pkgs) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- }
-
- // If we want to be lazy, filter everything that wasn't recently used.
- if (mLazyDexOpt) {
- filterRecentlyUsedApps(sortedPkgs);
- }
-
- int i = 0;
- int total = sortedPkgs.size();
- File dataDir = Environment.getDataDirectory();
- long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
- if (lowThreshold == 0) {
- throw new IllegalStateException("Invalid low memory threshold");
- }
- for (PackageParser.Package pkg : sortedPkgs) {
- long usableSpace = dataDir.getUsableSpace();
- if (usableSpace < lowThreshold) {
- Log.w(TAG, "Not running dexopt on remaining apps due to low memory: " + usableSpace);
- break;
- }
- performBootDexOpt(pkg, ++i, total);
- }
- }
- }
-
- private void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs) {
- // Filter out packages that aren't recently used.
- //
- // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
- // should do a full dexopt.
- if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
- int total = pkgs.size();
- int skipped = 0;
- long now = System.currentTimeMillis();
- for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
- PackageParser.Package pkg = i.next();
- long then = pkg.mLastPackageUsageTimeInMills;
- if (then + mDexOptLRUThresholdInMills < now) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " +
- ((then == 0) ? "never" : new Date(then)));
- }
- i.remove();
- skipped++;
- }
- }
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
- }
- }
}
private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
@@ -6300,54 +6131,36 @@
return pkgNames;
}
- private void performBootDexOpt(PackageParser.Package pkg, int curr, int total) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Optimizing app " + curr + " of " + total + ": " + pkg.packageName);
- }
- if (!isFirstBoot()) {
- try {
- ActivityManagerNative.getDefault().showBootMessage(
- mContext.getResources().getString(R.string.android_upgrading_apk,
- curr, total), true);
- } catch (RemoteException e) {
+ @Override
+ public void notifyPackageUse(String packageName) {
+ synchronized (mPackages) {
+ PackageParser.Package p = mPackages.get(packageName);
+ if (p == null) {
+ return;
}
- }
- PackageParser.Package p = pkg;
- synchronized (mInstallLock) {
- mPackageDexOptimizer.performDexOpt(p, null /* instruction sets */,
- false /* force dex */, false /* defer */, true /* include dependencies */,
- false /* boot complete */, false /*useJit*/);
+ p.mLastPackageUsageTimeInMills = System.currentTimeMillis();
}
}
@Override
public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
- return performDexOptTraced(packageName, instructionSet, false);
+ return performDexOptTraced(packageName, instructionSet);
}
- public boolean performDexOpt(
- String packageName, String instructionSet, boolean backgroundDexopt) {
- return performDexOptTraced(packageName, instructionSet, backgroundDexopt);
+ public boolean performDexOpt(String packageName, String instructionSet) {
+ return performDexOptTraced(packageName, instructionSet);
}
- private boolean performDexOptTraced(
- String packageName, String instructionSet, boolean backgroundDexopt) {
+ private boolean performDexOptTraced(String packageName, String instructionSet) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
try {
- return performDexOptInternal(packageName, instructionSet, backgroundDexopt);
+ return performDexOptInternal(packageName, instructionSet);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
- private boolean performDexOptInternal(
- String packageName, String instructionSet, boolean backgroundDexopt) {
- boolean dexopt = mLazyDexOpt || backgroundDexopt;
- boolean updateUsage = !backgroundDexopt; // Don't update usage if this is just a backgroundDexopt
- if (!dexopt && !updateUsage) {
- // We aren't going to dexopt or update usage, so bail early.
- return false;
- }
+ private boolean performDexOptInternal(String packageName, String instructionSet) {
PackageParser.Package p;
final String targetInstructionSet;
synchronized (mPackages) {
@@ -6355,14 +6168,7 @@
if (p == null) {
return false;
}
- if (updateUsage) {
- p.mLastPackageUsageTimeInMills = System.currentTimeMillis();
- }
mPackageUsage.write(false);
- if (!dexopt) {
- // We aren't going to dexopt, so bail early.
- return false;
- }
targetInstructionSet = instructionSet != null ? instructionSet :
getPrimaryInstructionSet(p.applicationInfo);
@@ -6375,8 +6181,7 @@
synchronized (mInstallLock) {
final String[] instructionSets = new String[] { targetInstructionSet };
int result = mPackageDexOptimizer.performDexOpt(p, instructionSets,
- false /* forceDex */, false /* defer */, true /* inclDependencies */,
- true /* boot complete */, false /*useJit*/);
+ true /* inclDependencies */);
return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
}
} finally {
@@ -6426,8 +6231,7 @@
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
final int res = mPackageDexOptimizer.performDexOpt(pkg, instructionSets,
- true /*forceDex*/, false /* defer */, true /* inclDependencies */,
- true /* boot complete */, false /*useJit*/);
+ true /* inclDependencies */);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
@@ -7217,7 +7021,7 @@
" secondary=" + pkg.applicationInfo.secondaryCpuAbi);
}
- if ((scanFlags&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
+ if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
// We don't do this here during boot because we can do it all
// at once after scanning all existing packages.
//
@@ -7225,21 +7029,9 @@
// we can avoid redundant dexopts, and also to make sure we've got the
// code and package path correct.
adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
- pkg, forceDex, (scanFlags & SCAN_DEFER_DEX) != 0, true /* boot complete */);
+ pkg, true /* boot complete */);
}
- if ((scanFlags & SCAN_NO_DEX) == 0) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-
- int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instruction sets */,
- forceDex, (scanFlags & SCAN_DEFER_DEX) != 0, false /* inclDependencies */,
- (scanFlags & SCAN_BOOTING) == 0, false /*useJit*/);
-
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
- throw new PackageManagerException(INSTALL_FAILED_DEXOPT, "scanPackageLI");
- }
- }
if (mFactoryTest && pkg.requestedPermissions.contains(
android.Manifest.permission.FACTORY_TEST)) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
@@ -7291,7 +7083,7 @@
+ name + " that is not declared on system image; skipping");
}
}
- if ((scanFlags&SCAN_BOOTING) == 0) {
+ if ((scanFlags & SCAN_BOOTING) == 0) {
// If we are not booting, we need to update any applications
// that are clients of our shared library. If we are booting,
// this will all be done once the scan is complete.
@@ -7301,30 +7093,6 @@
}
}
- // We also need to dexopt any apps that are dependent on this library. Note that
- // if these fail, we should abort the install since installing the library will
- // result in some apps being broken.
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
- try {
- if (clientLibPkgs != null) {
- if ((scanFlags & SCAN_NO_DEX) == 0) {
- for (int i = 0; i < clientLibPkgs.size(); i++) {
- PackageParser.Package clientPkg = clientLibPkgs.get(i);
- int result = mPackageDexOptimizer.performDexOpt(clientPkg,
- null /* instruction sets */, forceDex,
- (scanFlags & SCAN_DEFER_DEX) != 0, false,
- (scanFlags & SCAN_BOOTING) == 0, false /*useJit*/);
- if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
- throw new PackageManagerException(INSTALL_FAILED_DEXOPT,
- "scanPackageLI failed to dexopt clientLibPkgs");
- }
- }
- }
- }
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
-
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
@@ -7871,8 +7639,7 @@
* adds unnecessary complexity.
*/
private void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
- PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt,
- boolean bootComplete) {
+ PackageParser.Package scannedPackage, boolean bootComplete) {
String requiredInstructionSet = null;
if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) {
requiredInstructionSet = VMRuntime.getInstructionSet(
@@ -7934,22 +7701,8 @@
if (ps.pkg != null && ps.pkg.applicationInfo != null) {
ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi);
-
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-
- int result = mPackageDexOptimizer.performDexOpt(ps.pkg,
- null /* instruction sets */, forceDexOpt, deferDexOpt, true,
- bootComplete, false /*useJit*/);
-
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
- ps.primaryCpuAbiString = null;
- ps.pkg.applicationInfo.primaryCpuAbi = null;
- return;
- } else {
- mInstaller.rmdex(ps.codePathString,
- getDexCodeInstructionSet(getPreferredInstructionSet()));
- }
+ mInstaller.rmdex(ps.codePathString,
+ getDexCodeInstructionSet(getPreferredInstructionSet()));
}
}
}
@@ -12719,19 +12472,6 @@
res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");
return;
}
-
- // Run dexopt before old package gets removed, to minimize time when app is unavailable
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-
- int result = mPackageDexOptimizer
- .performDexOpt(pkg, null /* instruction sets */, false /* forceDex */,
- false /* defer */, false /* inclDependencies */,
- true /*bootComplete*/, quickInstall /*useJit*/);
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
- res.setError(INSTALL_FAILED_DEXOPT, "Dexopt failed for " + pkg.codePath);
- return;
- }
}
if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
@@ -16810,27 +16550,6 @@
}
}
- public void getUsageStatsIfNoPackageUsageInfo() {
- if (!mPackageUsage.isHistoricalPackageUsageAvailable()) {
- UsageStatsManager usm = (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE);
- if (usm == null) {
- throw new IllegalStateException("UsageStatsManager must be initialized");
- }
- long now = System.currentTimeMillis();
- Map<String, UsageStats> stats = usm.queryAndAggregateUsageStats(now - mDexOptLRUThresholdInMills, now);
- for (Map.Entry<String, UsageStats> entry : stats.entrySet()) {
- String packageName = entry.getKey();
- PackageParser.Package pkg = mPackages.get(packageName);
- if (pkg == null) {
- continue;
- }
- UsageStats usage = entry.getValue();
- pkg.mLastPackageUsageTimeInMills = usage.getLastTimeUsed();
- mPackageUsage.mIsHistoricalPackageUsageAvailable = true;
- }
- }
- }
-
/**
* Check and throw if the given before/after packages would be considered a
* downgrade.
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 4852f02..89f5658 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -1331,17 +1331,23 @@
}
}
+ private void clearAppTransitionState() {
+ mNextAppTransitionPackage = null;
+ mNextAppTransitionAnimationsSpecs.clear();
+ mDefaultNextAppTransitionAnimationSpec = null;
+ mAnimationFinishedCallback = null;
+ }
+
void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
IRemoteCallback startedCallback) {
if (isTransitionSet()) {
+ clearAppTransitionState();
mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
mNextAppTransitionPackage = packageName;
- mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionEnter = enterAnim;
mNextAppTransitionExit = exitAnim;
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
- mAnimationFinishedCallback = null;
} else {
postAnimationCallback();
}
@@ -1350,40 +1356,34 @@
void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
int startHeight) {
if (isTransitionSet()) {
+ clearAppTransitionState();
mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
- mNextAppTransitionPackage = null;
- mNextAppTransitionAnimationsSpecs.clear();
putDefaultNextAppTransitionCoordinates(startX, startY, startX + startWidth,
startY + startHeight, null);
postAnimationCallback();
- mNextAppTransitionCallback = null;
- mAnimationFinishedCallback = null;
}
}
void overridePendingAppTransitionClipReveal(int startX, int startY,
int startWidth, int startHeight) {
if (isTransitionSet()) {
+ clearAppTransitionState();
mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL;
putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight, null);
postAnimationCallback();
- mNextAppTransitionCallback = null;
- mAnimationFinishedCallback = null;
}
}
void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp) {
if (isTransitionSet()) {
+ clearAppTransitionState();
mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP
: NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN;
- mNextAppTransitionPackage = null;
- mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionScaleUp = scaleUp;
putDefaultNextAppTransitionCoordinates(startX, startY, 0, 0, srcThumb);
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
- mAnimationFinishedCallback = null;
} else {
postAnimationCallback();
}
@@ -1392,16 +1392,14 @@
void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) {
if (isTransitionSet()) {
+ clearAppTransitionState();
mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
: NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
- mNextAppTransitionPackage = null;
- mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionScaleUp = scaleUp;
putDefaultNextAppTransitionCoordinates(startX, startY, targetWidth, targetHeight,
srcThumb);
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
- mAnimationFinishedCallback = null;
} else {
postAnimationCallback();
}
@@ -1411,22 +1409,22 @@
IRemoteCallback onAnimationStartedCallback, IRemoteCallback onAnimationFinishedCallback,
boolean scaleUp) {
if (isTransitionSet()) {
+ clearAppTransitionState();
mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
: NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
- mNextAppTransitionPackage = null;
- mDefaultNextAppTransitionAnimationSpec = null;
- mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionScaleUp = scaleUp;
- for (int i = 0; i < specs.length; i++) {
- AppTransitionAnimationSpec spec = specs[i];
- if (spec != null) {
- mNextAppTransitionAnimationsSpecs.put(spec.taskId, spec);
- if (i == 0) {
- // In full screen mode, the transition code depends on the default spec to
- // be set.
- Rect rect = spec.rect;
- putDefaultNextAppTransitionCoordinates(rect.left, rect.top, rect.width(),
- rect.height(), null);
+ if (specs != null) {
+ for (int i = 0; i < specs.length; i++) {
+ AppTransitionAnimationSpec spec = specs[i];
+ if (spec != null) {
+ mNextAppTransitionAnimationsSpecs.put(spec.taskId, spec);
+ if (i == 0) {
+ // In full screen mode, the transition code depends on the default spec
+ // to be set.
+ Rect rect = spec.rect;
+ putDefaultNextAppTransitionCoordinates(rect.left, rect.top,
+ rect.width(), rect.height(), null);
+ }
}
}
}
@@ -1442,11 +1440,9 @@
IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
boolean scaleUp) {
if (isTransitionSet()) {
+ clearAppTransitionState();
mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
: NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
- mNextAppTransitionPackage = null;
- mDefaultNextAppTransitionAnimationSpec = null;
- mNextAppTransitionAnimationsSpecs.clear();
mNextAppTransitionAnimationsSpecsFuture = specsFuture;
mNextAppTransitionScaleUp = scaleUp;
mNextAppTransitionFutureCallback = callback;
@@ -1455,10 +1451,10 @@
void overrideInPlaceAppTransition(String packageName, int anim) {
if (isTransitionSet()) {
+ clearAppTransitionState();
mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE;
mNextAppTransitionPackage = packageName;
mNextAppTransitionInPlace = anim;
- mAnimationFinishedCallback = null;
} else {
postAnimationCallback();
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index c47c377..1caeca0 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -188,9 +188,10 @@
}
@Override
- public void repositionChild(IWindow window, int x, int y, long deferTransactionUntilFrame,
- Rect outFrame) {
- mService.repositionChild(this, window, x, y, deferTransactionUntilFrame, outFrame);
+ public void repositionChild(IWindow window, int left, int top, int right, int bottom,
+ long deferTransactionUntilFrame, Rect outFrame) {
+ mService.repositionChild(this, window, left, top, right, bottom,
+ deferTransactionUntilFrame, outFrame);
}
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6aaf3c7..7c92684 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -135,7 +135,7 @@
stack.addTask(this, toTop);
}
- void positionTaskInStack(TaskStack stack, int position) {
+ void positionTaskInStack(TaskStack stack, int position, Rect bounds, Configuration config) {
if (mStack != null && stack != mStack) {
if (DEBUG_STACK) Slog.i(TAG, "positionTaskInStack: removing taskId=" + mTaskId
+ " from stack=" + mStack);
@@ -143,6 +143,7 @@
mStack.removeTask(this);
}
stack.positionTask(this, position, showForAllUsers());
+ setBounds(bounds, config);
}
boolean removeAppToken(AppWindowToken wtoken) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e98333e..d9af27d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2505,7 +2505,8 @@
}
void repositionChild(Session session, IWindow client,
- int x, int y, long deferTransactionUntilFrame, Rect outFrame) {
+ int top, int left, int right, int bottom,
+ long deferTransactionUntilFrame, Rect outFrame) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild");
long origId = Binder.clearCallingIdentity();
@@ -2521,8 +2522,10 @@
+ "attached to a parent win=" + win);
}
- win.mFrame.left = x;
- win.mFrame.top = y;
+ win.mFrame.left = left;
+ win.mFrame.top = top;
+ win.mFrame.right = right;
+ win.mFrame.bottom = bottom;
win.mWinAnimator.computeShownFrameLocked();
@@ -2595,6 +2598,15 @@
throw new IllegalArgumentException(
"Window type can not be changed after the window is added.");
}
+
+ // Odd choice but less odd than embedding in copyFrom()
+ if ((attrs.flags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) != 0) {
+ attrs.x = win.mAttrs.x;
+ attrs.y = win.mAttrs.y;
+ attrs.width = win.mAttrs.width;
+ attrs.height = win.mAttrs.height;
+ }
+
flagChanges = win.mAttrs.flags ^= attrs.flags;
attrChanges = win.mAttrs.copyFrom(attrs);
if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
@@ -4795,7 +4807,8 @@
}
}
- public void positionTaskInStack(int taskId, int stackId, int position) {
+ public void positionTaskInStack(int taskId, int stackId, int position, Rect bounds,
+ Configuration config) {
synchronized (mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG, "positionTaskInStack: positioning taskId=" + taskId
+ " in stackId=" + stackId + " at " + position);
@@ -4811,7 +4824,7 @@
"positionTaskInStack: could not find stackId=" + stackId);
return;
}
- task.positionTaskInStack(stack, position);
+ task.positionTaskInStack(stack, position, bounds, config);
final DisplayContent displayContent = stack.getDisplayContent();
displayContent.layoutNeeded = true;
mWindowPlacerLocked.performSurfacePlacement();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c7b638c..080a2d1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1355,6 +1355,14 @@
}
void applyDimLayerIfNeeded() {
+ // When the app is terminated (eg. from Recents), the task might have already been
+ // removed with the window pending removal. Don't apply dim in such cases, as there
+ // will be no more updateDimLayer() calls, which leaves the dimlayer invalid.
+ final AppWindowToken token = mAppToken;
+ if (token != null && token.removed) {
+ return;
+ }
+
if (!mExiting && mAppDied) {
// If app died visible, apply a dim over the window to indicate that it's inactive
mDisplayContent.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1e32f60..eee7d92 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -156,6 +156,11 @@
/**
* Implementation of the device policy APIs.
+ *
+ * Locking policies:
+ * - {@link DevicePolicyManagerService} must not call into {@link IActivityManager} within {@code
+ * this} lock to avoid lock inversion.
+ * - Methods that call into {@link IActivityManager} must have the "AM" suffix.
*/
public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@@ -1105,7 +1110,7 @@
.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
}
- IActivityManager getIActivityManager() {
+ IActivityManager getIActivityManagerInner() {
return ActivityManagerNative.getDefault();
}
@@ -1236,6 +1241,16 @@
}
/**
+ * Caller must not hold {@code this} lock. See also the class javadoc.
+ */
+ final IActivityManager getIActivityManager() {
+ if (Thread.holdsLock(this)) {
+ Slog.wtfStack(LOG_TAG, "Call to ActivityManager detected within DPMS lock");
+ }
+ return mInjector.getIActivityManagerInner();
+ }
+
+ /**
* Instantiates the service.
*/
public DevicePolicyManagerService(Context context) {
@@ -1349,8 +1364,6 @@
// TODO PO may not have a class name either due to b/17652534. Address that too.
- updateDeviceOwnerLocked();
-
// TODO Notify UM to update restrictions (?)
}
}
@@ -2037,36 +2050,23 @@
validatePasswordOwnerLocked(policy);
updateMaximumTimeToLockLocked(policy);
- updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
+ updateLockTaskPackages(policy.mLockTaskPackages, userHandle);
if (policy.mStatusBarDisabled) {
setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
}
}
- private void updateLockTaskPackagesLocked(List<String> packages, int userId) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- mInjector.getIActivityManager()
- .updateLockTaskPackages(userId, packages.toArray(new String[packages.size()]));
- } catch (RemoteException e) {
- // Not gonna happen.
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
- }
-
- private void updateDeviceOwnerLocked() {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- if (getDeviceOwner() != null) {
- mInjector.getIActivityManager()
- .updateDeviceOwner(getDeviceOwner().getPackageName());
+ private void updateLockTaskPackages(List<String> packages, final int userId) {
+ final String[] copy = packages.toArray(new String[packages.size()]);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ getIActivityManager().updateLockTaskPackages(userId, copy);
+ } catch (RemoteException willNotHappen) {
+ }
}
- } catch (RemoteException e) {
- // Not gonna happen.
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
static void validateQualityConstant(int quality) {
@@ -2137,14 +2137,21 @@
}
private void ensureDeviceOwnerUserStarted() {
- if (mOwners.hasDeviceOwner()) {
- final int userId = mOwners.getDeviceOwnerUserId();
- if (VERBOSE_LOG) {
- Log.v(LOG_TAG, "Starting non-system DO user: " + userId);
- }
- if (userId != UserHandle.USER_SYSTEM) {
+ if (!mOwners.hasDeviceOwner()) {
+ return;
+ }
+ final int userId = mOwners.getDeviceOwnerUserId();
+ if (userId == UserHandle.USER_SYSTEM) {
+ return;
+ }
+ if (VERBOSE_LOG) {
+ Log.v(LOG_TAG, "Starting non-system DO user: " + userId);
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
try {
- mInjector.getIActivityManager().startUserInBackground(userId);
+ getIActivityManager().startUserInBackground(userId);
// STOPSHIP Prevent the DO user from being killed.
@@ -2152,7 +2159,7 @@
Slog.w(LOG_TAG, "Exception starting user", e);
}
}
- }
+ });
}
private void cleanUpOldUsers() {
@@ -2418,17 +2425,21 @@
}
enforceCrossUserPermission(userHandle);
synchronized (this) {
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- if (policy.mAdminList.get(i).info.getPackageName().equals(packageName)) {
- return true;
- }
- }
- return false;
+ return packageHasActiveAdminsLocked(packageName, userHandle);
}
}
+ boolean packageHasActiveAdminsLocked(String packageName, int userHandle) {
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
+ for (int i = 0; i < N; i++) {
+ if (policy.mAdminList.get(i).info.getPackageName().equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {
if (!mHasFeature) {
@@ -3729,7 +3740,7 @@
@Override
public void run() {
try {
- IActivityManager am = mInjector.getIActivityManager();
+ IActivityManager am = getIActivityManager();
if (am.getCurrentUser().id == userHandle) {
am.switchUser(UserHandle.USER_SYSTEM);
}
@@ -4485,7 +4496,6 @@
mOwners.setDeviceOwner(admin, ownerName, userId);
mOwners.writeDeviceOwner();
- updateDeviceOwnerLocked();
Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
ident = mInjector.binderClearCallingIdentity();
@@ -4587,7 +4597,6 @@
mOwners.clearDeviceOwner();
mOwners.writeDeviceOwner();
- updateDeviceOwnerLocked();
// Reactivate backup service.
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -5348,14 +5357,14 @@
}
}
- private boolean checkCallerIsCurrentUserOrProfile() {
+ private boolean checkCallerIsCurrentUserOrProfileAM() {
int callingUserId = UserHandle.getCallingUserId();
long token = mInjector.binderClearCallingIdentity();
try {
UserInfo currentUser;
UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
try {
- currentUser = mInjector.getIActivityManager().getCurrentUser();
+ currentUser = getIActivityManager().getCurrentUser();
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to talk to activity managed.", e);
return false;
@@ -5386,7 +5395,7 @@
// TODO When InputMethodManager supports per user calls remove
// this restriction.
- if (!checkCallerIsCurrentUserOrProfile()) {
+ if (!checkCallerIsCurrentUserOrProfileAM()) {
return false;
}
@@ -5438,7 +5447,7 @@
public List getPermittedInputMethodsForCurrentUser() {
UserInfo currentUser;
try {
- currentUser = mInjector.getIActivityManager().getCurrentUser();
+ currentUser = getIActivityManager().getCurrentUser();
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to make remote calls to get current user", e);
// Activity managed is dead, just allow all IMEs
@@ -5533,7 +5542,7 @@
}
// Start user in background.
- mInjector.getIActivityManager().startUserInBackground(userHandle);
+ getIActivityManager().startUserInBackground(userHandle);
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to make remote calls for configureUser", e);
}
@@ -5566,20 +5575,20 @@
Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ }
- long id = mInjector.binderClearCallingIdentity();
- try {
- int userId = UserHandle.USER_SYSTEM;
- if (userHandle != null) {
- userId = userHandle.getIdentifier();
- }
- return mInjector.getIActivityManager().switchUser(userId);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Couldn't switch user", e);
- return false;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
+ long id = mInjector.binderClearCallingIdentity();
+ try {
+ int userId = UserHandle.USER_SYSTEM;
+ if (userHandle != null) {
+ userId = userHandle.getIdentifier();
}
+ return getIActivityManager().switchUser(userId);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Couldn't switch user", e);
+ return false;
+ } finally {
+ mInjector.binderRestoreCallingIdentity(id);
}
}
@@ -6051,7 +6060,7 @@
// Store the settings persistently.
saveSettingsLocked(userHandle);
- updateLockTaskPackagesLocked(packages, userHandle);
+ updateLockTaskPackages(packages, userHandle);
}
/**
@@ -6419,6 +6428,16 @@
}
}
+ @Override
+ public boolean isDeviceAdminPackage(int userId, String packageName) {
+ if (packageName == null) {
+ return false;
+ }
+ synchronized (DevicePolicyManagerService.this) {
+ return packageHasActiveAdminsLocked(packageName, userId);
+ }
+ }
+
private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
synchronized (DevicePolicyManagerService.this) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e32af5c..2f33d7c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -407,8 +407,6 @@
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));
- // Update after UsageStatsService is available, needed before performBootDexOpt.
- mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();
// Tracks whether the updatable WebView is in a ready state and watches for update installs.
mSystemServiceManager.startService(WebViewUpdateService.class);
@@ -612,11 +610,11 @@
// as appropriate.
mSystemServiceManager.startService(UiModeManagerService.class);
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "PerformBootDexOpt");
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "PerformFstrimIfNeeded");
try {
- mPackageManagerService.performBootDexOpt();
+ mPackageManagerService.performFstrimIfNeeded();
} catch (Throwable e) {
- reportWtf("performing boot dexopt", e);
+ reportWtf("performing fstrim", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
@@ -1319,4 +1317,4 @@
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, name);
Slog.i(TAG, name);
}
-}
\ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 2c01b8a..6419338 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -128,7 +128,7 @@
}
@Override
- IActivityManager getIActivityManager() {
+ IActivityManager getIActivityManagerInner() {
return context.iactivityManager;
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 36980e3..ca3d950 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -476,10 +476,6 @@
// Fire!
assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
- // Verify internal calls.
- verify(mContext.iactivityManager, times(1)).updateDeviceOwner(
- eq(admin1.getPackageName()));
-
// TODO We should check if the caller has called clearCallerIdentity().
verify(mContext.ibackupManager, times(1)).setBackupServiceActive(
eq(UserHandle.USER_SYSTEM), eq(false));
@@ -546,10 +542,6 @@
dpm.setActiveAdmin(admin1, /* replace =*/ false);
assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
- // Verify internal calls.
- verify(mContext.iactivityManager, times(1)).updateDeviceOwner(
- eq(admin1.getPackageName()));
-
assertEquals(admin1.getPackageName(), dpm.getDeviceOwner());
// Set up other mocks.
@@ -584,10 +576,6 @@
dpm.setActiveAdmin(admin1, /* replace =*/ false);
assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
- // Verify internal calls.
- verify(mContext.iactivityManager, times(1)).updateDeviceOwner(
- eq(admin1.getPackageName()));
-
assertEquals(admin1.getPackageName(), dpm.getDeviceOwner());
// Now call clear from the secondary user, which should throw.
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 013154b..f078a35 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -218,7 +218,7 @@
synchronized (this) {
mScreenOnTime = readScreenOnTimeLocked();
}
- mDisplayManager.registerDisplayListener(mDisplayListener, null);
+ mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
synchronized (this) {
updateDisplayLocked();
}
diff --git a/tests/NetworkSecurityConfigTest/res/raw/test_debug_ca.pem b/tests/NetworkSecurityConfigTest/res/raw/test_debug_ca.pem
new file mode 100644
index 0000000..81648d9
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/raw/test_debug_ca.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDITCCAgmgAwIBAgIJAP/YiWztz/J7MA0GCSqGSIb3DQEBCwUAMCcxFjAUBgNV
+BAMMDVRlc3QgZGVidWcgQ0ExDTALBgNVBAoMBEFPU1AwHhcNMTUxMTA5MjEyNjQ2
+WhcNMTgwODI5MjEyNjQ2WjAnMRYwFAYDVQQDDA1UZXN0IGRlYnVnIENBMQ0wCwYD
+VQQKDARBT1NQMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuPFmkOJj
+ehjfvdDr2qTcBWNqNATrW1SuM88Vj00ubUFQ4tZElozj8YnQOw1FeC79c1k88b8R
+6jcqYYp/mw2JYoD6yWcFPHo5BplIpk0EhIUARH/aeoclHvsUN2GGDyTO0vf0CfJn
+9Wp6lSLjyq7V/6tYdk+0cL632t56MHp8TCO+AaveYP1T8JZqx0/50xNcsK7lIqNa
+ctWyRGFxR4ifdVsgkw9WhAB/Ow2uOwN9uLGqzsCd+yXW2weX52EIivoTGZfJo+U8
+Fi0ygnCHBv2jsJA7yWLhHmZ4ijsVtfutIKmN0w+DHkl6S25girXhy0zJp/1QvHGm
+jaF60V1gw471jQIDAQABo1AwTjAdBgNVHQ4EFgQUoq66jncy83L5eeyW1g78s/uq
+iyQwHwYDVR0jBBgwFoAUoq66jncy83L5eeyW1g78s/uqiyQwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAohytuH4CdX0gO8EGVDRVurRH7LO69lwd/6Iw
+hJ1lIK/mzj5RM2itVGTkintyHCLu5giVkHn4FHg4X9qzZaTPOcXv9ntQNS2nacZe
+bY8nfhsAhstJT4nIOWHE3FrZkMDOK6nZHIzfscX3V/VVq5MeA+WzXwmKp6MBNr+E
+oUegXCGjd26Bl6SFz3rD7Qh+dzSTtyf/ECzXaMjpZu3k6fb4EgRz6vdBCHKKtpv6
+Mxcr0nLwdI6LnAGXvJLV4sj+l6Ngg00EeyorG8ATgtmsUrXXOR1e+yDCQv6fjQfs
+CWYztECAUE9hfCXJwb0TBrq9YeJAvcO7iE6S0Pq+X3xNtetE1A==
+-----END CERTIFICATE-----
diff --git a/tests/NetworkSecurityConfigTest/res/xml/debug_basic.xml b/tests/NetworkSecurityConfigTest/res/xml/debug_basic.xml
new file mode 100644
index 0000000..8da9317
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/debug_basic.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <base-config>
+ <trust-anchors>
+ </trust-anchors>
+ </base-config>
+ <debug-overrides>
+ <trust-anchors>
+ <certificates src="system" />
+ </trust-anchors>
+ </debug-overrides>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/debug_domain.xml b/tests/NetworkSecurityConfigTest/res/xml/debug_domain.xml
new file mode 100644
index 0000000..24eed7a
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/debug_domain.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <domain-config>
+ <domain>android.com</domain>
+ <trust-anchors>
+ <certificates src="@raw/ca_certs_pem" />
+ </trust-anchors>
+ </domain-config>
+ <debug-overrides>
+ <trust-anchors>
+ <certificates src="@raw/test_debug_ca" />
+ </trust-anchors>
+ </debug-overrides>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/debug_inherit.xml b/tests/NetworkSecurityConfigTest/res/xml/debug_inherit.xml
new file mode 100644
index 0000000..ce0cbc8
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/debug_inherit.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <debug-overrides>
+ <trust-anchors>
+ <certificates src="@raw/test_debug_ca" />
+ </trust-anchors>
+ </debug-overrides>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java
index 43c0e57..f7590fd 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java
@@ -22,6 +22,7 @@
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
import junit.framework.Assert;
@@ -69,8 +70,11 @@
public static SSLContext getSSLContext(ConfigSource source) throws Exception {
ApplicationConfig config = new ApplicationConfig(source);
+ TrustManagerFactory tmf =
+ TrustManagerFactory.getInstance("PKIX", new NetworkSecurityConfigProvider());
+ tmf.init(new RootTrustManagerFactorySpi.ApplicationConfigParameters(config));
SSLContext context = SSLContext.getInstance("TLS");
- context.init(null, new TrustManager[] {config.getTrustManager()}, null);
+ context.init(null, tmf.getTrustManagers(), null);
return context;
}
}
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
index f52a279..c6f3680 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
@@ -24,15 +24,23 @@
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.Security;
+import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Set;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
public class XmlConfigTests extends AndroidTestCase {
+ private final static String DEBUG_CA_SUBJ = "O=AOSP, CN=Test debug CA";
+
public void testEmptyConfigFile() throws Exception {
XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.empty_config);
ApplicationConfig appConfig = new ApplicationConfig(source);
@@ -274,6 +282,68 @@
assertFalse(child.isCleartextTrafficPermitted());
}
+ public void testDebugOverridesDisabled() throws Exception {
+ XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.debug_basic, false);
+ ApplicationConfig appConfig = new ApplicationConfig(source);
+ NetworkSecurityConfig config = appConfig.getConfigForHostname("");
+ Set<TrustAnchor> anchors = config.getTrustAnchors();
+ MoreAsserts.assertEmpty(anchors);
+ SSLContext context = TestUtils.getSSLContext(source);
+ TestUtils.assertConnectionFails(context, "android.com", 443);
+ TestUtils.assertConnectionFails(context, "developer.android.com", 443);
+ }
+
+ public void testBasicDebugOverrides() throws Exception {
+ XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.debug_basic, true);
+ ApplicationConfig appConfig = new ApplicationConfig(source);
+ NetworkSecurityConfig config = appConfig.getConfigForHostname("");
+ Set<TrustAnchor> anchors = config.getTrustAnchors();
+ MoreAsserts.assertNotEmpty(anchors);
+ for (TrustAnchor anchor : anchors) {
+ assertTrue(anchor.overridesPins);
+ }
+ SSLContext context = TestUtils.getSSLContext(source);
+ TestUtils.assertConnectionSucceeds(context, "android.com", 443);
+ TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
+ }
+
+ public void testDebugOverridesWithDomain() throws Exception {
+ XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.debug_domain, true);
+ ApplicationConfig appConfig = new ApplicationConfig(source);
+ NetworkSecurityConfig config = appConfig.getConfigForHostname("android.com");
+ Set<TrustAnchor> anchors = config.getTrustAnchors();
+ boolean foundDebugCA = false;
+ for (TrustAnchor anchor : anchors) {
+ if (anchor.certificate.getSubjectDN().toString().equals(DEBUG_CA_SUBJ)) {
+ foundDebugCA = true;
+ assertTrue(anchor.overridesPins);
+ }
+ }
+ assertTrue(foundDebugCA);
+ SSLContext context = TestUtils.getSSLContext(source);
+ TestUtils.assertConnectionSucceeds(context, "android.com", 443);
+ TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
+ }
+
+ public void testDebugInherit() throws Exception {
+ XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.debug_domain, true);
+ ApplicationConfig appConfig = new ApplicationConfig(source);
+ NetworkSecurityConfig config = appConfig.getConfigForHostname("android.com");
+ Set<TrustAnchor> anchors = config.getTrustAnchors();
+ boolean foundDebugCA = false;
+ for (TrustAnchor anchor : anchors) {
+ if (anchor.certificate.getSubjectDN().toString().equals(DEBUG_CA_SUBJ)) {
+ foundDebugCA = true;
+ assertTrue(anchor.overridesPins);
+ }
+ }
+ assertTrue(foundDebugCA);
+ assertTrue(anchors.size() > 1);
+ SSLContext context = TestUtils.getSSLContext(source);
+ TestUtils.assertConnectionSucceeds(context, "android.com", 443);
+ TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
+ }
+
private void testBadConfig(int configId) throws Exception {
try {
XmlConfigSource source = new XmlConfigSource(getContext(), configId);
@@ -310,4 +380,26 @@
public void testBadConfig5() throws Exception {
testBadConfig(R.xml.bad_config4);
}
+
+ public void testTrustManagerKeystore() throws Exception {
+ XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.bad_pin, true);
+ ApplicationConfig appConfig = new ApplicationConfig(source);
+ Provider provider = new NetworkSecurityConfigProvider();
+ TrustManagerFactory tmf =
+ TrustManagerFactory.getInstance("PKIX", provider);
+ KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keystore.load(null);
+ int i = 0;
+ for (X509Certificate cert : SystemCertificateSource.getInstance().getCertificates()) {
+ keystore.setEntry(String.valueOf(i),
+ new KeyStore.TrustedCertificateEntry(cert),
+ null);
+ i++;
+ }
+ tmf.init(keystore);
+ TrustManager[] tms = tmf.getTrustManagers();
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, tms, null);
+ TestUtils.assertConnectionSucceeds(context, "android.com" , 443);
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 11bd15d..1ec0547 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -95,8 +95,8 @@
}
@Override
- public void repositionChild(IWindow childWindow, int x, int y, long deferTransactionUntilFrame,
- Rect outFrame) {
+ public void repositionChild(IWindow childWindow, int x, int y, int width, int height,
+ long deferTransactionUntilFrame, Rect outFrame) {
// pass for now.
return;
}